Re: [PATCH 1/4] v4l: vsp1: Implement partition algorithm restrictions
Hi Laurent, Kieran > > > Testing SRU-UDS scaling 768x576 - 768x576 - 640x480 in RGB24: fail > > > Testing SRU-UDS scaling 768x576 - 768x576 - 768x576 in RGB24: pass > > > Testing SRU-UDS scaling 768x576 - 768x576 - 1024x768 in RGB24: pass > > > Testing SRU-UDS scaling 768x576 - 1536x1152 - 1280x960 in RGB24: pass > > > Testing SRU-UDS scaling 768x576 - 1536x1152 - 1536x1152 in RGB24: pass > > > Testing SRU-UDS scaling 768x576 - 1536x1152 - 2048x1536 in RGB24: pass > > > Testing UDS-SRU scaling 768x576 - 640x480 - 640x480 in RGB24: pass > > > Testing UDS-SRU scaling 768x576 - 640x480 - 1280x960 in RGB24: pass > > > Testing UDS-SRU scaling 768x576 - 768x576 - 768x576 in RGB24: pass > > > Testing UDS-SRU scaling 768x576 - 768x576 - 1536x1152 in RGB24: pass > > > Testing UDS-SRU scaling 768x576 - 1024x768 - 1024x768 in RGB24: pass > > > Testing UDS-SRU scaling 768x576 - 1024x768 - 2048x1536 in RGB24: pass > > > Testing SRU-UDS scaling 768x576 - 768x576 - 640x480 in YUV444M: fail > > > Testing SRU-UDS scaling 768x576 - 768x576 - 768x576 in YUV444M: pass > > > Testing SRU-UDS scaling 768x576 - 768x576 - 1024x768 in YUV444M: pass > > > Testing SRU-UDS scaling 768x576 - 1536x1152 - 1280x960 in YUV444M: pass > > > Testing SRU-UDS scaling 768x576 - 1536x1152 - 1536x1152 in YUV444M: pass > > > Testing SRU-UDS scaling 768x576 - 1536x1152 - 2048x1536 in YUV444M: hangs > > > Testing UDS-SRU scaling 768x576 - 640x480 - 640x480 in YUV444M: pass > > > Testing UDS-SRU scaling 768x576 - 640x480 - 1280x960 in YUV444M: fail > > > Testing UDS-SRU scaling 768x576 - 768x576 - 768x576 in YUV444M: pass > > > Testing UDS-SRU scaling 768x576 - 768x576 - 1536x1152 in YUV444M: pass > > > Testing UDS-SRU scaling 768x576 - 1024x768 - 1024x768 in YUV444M: pass > > > Testing UDS-SRU scaling 768x576 - 1024x768 - 2048x1536 in YUV444M: hangs > > (snip) > > > However, from the above tests it looks like the hardware can live with > > > more > > > relaxed restrictions than the ones implemented here. I haven't tested all > > > UDS > > > scaling ratios, and certainly not under all memory bus load conditions, I > > > might thus be too optimistic. Morimoto-san, would it be possible to get > > > more > > > information about this from the hardware team, to check whether the above > > > two > > > restrictions need to be honoured, or whether they come from an older > > > hardware > > > version ? > > > > I asked it to HW team. > > Please wait I'm still waiting from HW team's response, but can you check "32.3.7 Image partition for VSPI processing" on v0.53 datasheet ? (v0.53 is for ES2.0, but this chapter should be same for ES1.x / ES2.0) You may / may not find something from here Best regards --- Kuninori Morimoto
RE: [PATCH] phy: core: fix the condition to enable pm_runtime in phy_create()
Hi, > From: Yoshihiro Shimoda > Sent: Friday, March 03, 2017 8:33 PM > > This patch fixes an issue that phy_create() never enables the pm_runtime. > And then, we can remove calling the pm_runtime_{en,dis}able from some > phy drivers. > > Fixes: ff764963479a ("drivers: phy: add generic PHY framework") > Cc: sta...@vger.kernel.org # v3.13+ > Signed-off-by: Yoshihiro Shimoda I would like to recall this patch because I completely misunderstand this condition. I apologize for that. Best regards, Yoshihiro Shimoda
[GIT PULL FOR renesas-drivers] DU + VSP display flicker fixes
Hi Geert, (Resending with the linux-renesas-soc mailing list CC'ed, sorry about the trouble) The following changes since commit a10afcaf9d180e2cc1dff623081e12fe5275fd38: Merge branch 'vsp1/next' into HEAD (2017-03-05 01:55:06 +0200) are available in the git repository at: git://linuxtv.org/pinchartl/media.git tags/drm-next-du-vsp-v3-20170305 for you to fetch changes up to 6208a2aec17b45be0d10921135c112c57138bca0: drm: rcar-du: Register a completion callback with VSP1 (2017-03-06 03:05:58 +0200) Kieran Bingham (4): v4l: vsp1: Adapt vsp1_du_setup_lif() interface to use a structure v4l: vsp1: Postpone frame end handling in event of display list race v4l: vsp1: Extend VSP1 module API to allow DRM callbacks drm: rcar-du: Register a completion callback with VSP1 Laurent Pinchart (1): drm: rcar-du: Arm the page flip event after queuing the page flip drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 30 ++--- drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 1 + drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 17 -- drivers/media/platform/vsp1/vsp1_dl.c | 19 ++-- drivers/media/platform/vsp1/vsp1_dl.h | 2 +- drivers/media/platform/vsp1/vsp1_drm.c | 50 drivers/media/platform/vsp1/vsp1_drm.h | 11 + drivers/media/platform/vsp1/vsp1_pipe.c | 13 ++- include/media/vsp1.h| 20 +++-- 9 files changed, 125 insertions(+), 38 deletions(-) -- Regards, Laurent Pinchart
[GIT PULL FOR renesas-drivers] VSP1 rotation and histogram
Hi Geert, The following changes since commit 130f8756b9b83c0137ee0d587152a7ef3e10f74b: v4l: vsp1: Register pipe with output WPF (2017-03-05 01:53:46 +0200) are available in the git repository at: git://linuxtv.org/pinchartl/media.git vsp1/histogram for you to fetch changes up to 8bcdadfb22f218a42dc07b502c2a7ffc56509874: v4l: vsp1: Add HGT support (2017-03-06 02:39:38 +0200) Laurent Pinchart (8): v4l: Clearly document interactions between formats, controls and buffers v4l: vsp1: wpf: Implement rotation support v4l: Add metadata buffer type and format v4l: vsp1: Add histogram support v4l: vsp1: Support histogram generators in pipeline configuration v4l: vsp1: Fix HGO and HGT routing register addresses v4l: Define a pixel format for the R-Car VSP1 1-D histogram engine v4l: vsp1: Add HGO support Niklas Söderlund (2): v4l: Define a pixel format for the R-Car VSP1 2-D histogram engine v4l: vsp1: Add HGT support Documentation/media/uapi/v4l/buffer.rst | 111 + Documentation/media/uapi/v4l/dev-meta.rst | 62 +++ Documentation/media/uapi/v4l/devices.rst | 1 + Documentation/media/uapi/v4l/meta-formats.rst | 16 + Documentation/media/uapi/v4l/pixfmt-meta-vsp1-hgo.rst | 168 +++ Documentation/media/uapi/v4l/pixfmt-meta-vsp1-hgt.rst | 120 + Documentation/media/uapi/v4l/pixfmt.rst | 1 + Documentation/media/uapi/v4l/vidioc-querycap.rst | 3 + Documentation/media/videodev2.h.rst.exceptions| 2 + drivers/media/platform/Kconfig| 1 + drivers/media/platform/vsp1/Makefile | 1 + drivers/media/platform/vsp1/vsp1.h| 6 + drivers/media/platform/vsp1/vsp1_drm.c| 2 +- drivers/media/platform/vsp1/vsp1_drv.c| 70 ++- drivers/media/platform/vsp1/vsp1_entity.c | 154 +- drivers/media/platform/vsp1/vsp1_entity.h | 8 +- drivers/media/platform/vsp1/vsp1_hgo.c| 228 + drivers/media/platform/vsp1/vsp1_hgo.h| 45 ++ drivers/media/platform/vsp1/vsp1_hgt.c| 222 + drivers/media/platform/vsp1/vsp1_hgt.h| 42 ++ drivers/media/platform/vsp1/vsp1_histo.c | 646 + drivers/media/platform/vsp1/vsp1_histo.h | 84 drivers/media/platform/vsp1/vsp1_pipe.c | 38 +- drivers/media/platform/vsp1/vsp1_pipe.h | 4 + drivers/media/platform/vsp1/vsp1_regs.h | 33 +- drivers/media/platform/vsp1/vsp1_rpf.c| 2 +- drivers/media/platform/vsp1/vsp1_rwpf.c | 5 + drivers/media/platform/vsp1/vsp1_rwpf.h | 7 +- drivers/media/platform/vsp1/vsp1_video.c | 42 +- drivers/media/platform/vsp1/vsp1_wpf.c| 205 ++-- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 19 + drivers/media/v4l2-core/v4l2-dev.c| 16 +- drivers/media/v4l2-core/v4l2-ioctl.c | 36 ++ drivers/media/v4l2-core/videobuf2-v4l2.c | 3 + include/media/v4l2-ioctl.h| 17 + include/trace/events/v4l2.h | 1 + include/uapi/linux/videodev2.h| 17 + 37 files changed, 2336 insertions(+), 102 deletions(-) create mode 100644 Documentation/media/uapi/v4l/dev-meta.rst create mode 100644 Documentation/media/uapi/v4l/meta-formats.rst create mode 100644 Documentation/media/uapi/v4l/pixfmt-meta-vsp1-hgo.rst create mode 100644 Documentation/media/uapi/v4l/pixfmt-meta-vsp1-hgt.rst create mode 100644 drivers/media/platform/vsp1/vsp1_hgo.c create mode 100644 drivers/media/platform/vsp1/vsp1_hgo.h create mode 100644 drivers/media/platform/vsp1/vsp1_hgt.c create mode 100644 drivers/media/platform/vsp1/vsp1_hgt.h create mode 100644 drivers/media/platform/vsp1/vsp1_histo.c create mode 100644 drivers/media/platform/vsp1/vsp1_histo.h -- Regards, Laurent Pinchart
[PATCH v2.1 3/3] v4l: vsp1: wpf: Implement rotation support
Some WPF instances, on Gen3 devices, can perform 90° rotation when writing frames to memory. Implement support for this using the V4L2_CID_ROTATE control. Signed-off-by: Laurent Pinchart --- Changes since v2: - Store controls in distinct fields instead of array. --- drivers/media/platform/vsp1/vsp1_rpf.c | 2 +- drivers/media/platform/vsp1/vsp1_rwpf.c | 5 + drivers/media/platform/vsp1/vsp1_rwpf.h | 7 +- drivers/media/platform/vsp1/vsp1_video.c | 12 +- drivers/media/platform/vsp1/vsp1_wpf.c | 205 +++ 5 files changed, 177 insertions(+), 54 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c index f5a9a4c8c74d..8feddd59cf8d 100644 --- a/drivers/media/platform/vsp1/vsp1_rpf.c +++ b/drivers/media/platform/vsp1/vsp1_rpf.c @@ -106,7 +106,7 @@ static void rpf_configure(struct vsp1_entity *entity, * of the pipeline. */ output = vsp1_entity_get_pad_format(wpf, wpf->config, - RWPF_PAD_SOURCE); + RWPF_PAD_SINK); crop.width = pipe->partition.width * input_width / output->width; diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.c b/drivers/media/platform/vsp1/vsp1_rwpf.c index 7d52c88a583e..cfd8f1904fa6 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.c +++ b/drivers/media/platform/vsp1/vsp1_rwpf.c @@ -121,6 +121,11 @@ static int vsp1_rwpf_set_format(struct v4l2_subdev *subdev, RWPF_PAD_SOURCE); *format = fmt->format; + if (rwpf->flip.rotate) { + format->width = fmt->format.height; + format->height = fmt->format.width; + } + done: mutex_unlock(&rwpf->entity.lock); return ret; diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h index 1c98aff3da5d..58215a7ab631 100644 --- a/drivers/media/platform/vsp1/vsp1_rwpf.h +++ b/drivers/media/platform/vsp1/vsp1_rwpf.h @@ -56,9 +56,14 @@ struct vsp1_rwpf { struct { spinlock_t lock; - struct v4l2_ctrl *ctrls[2]; + struct { + struct v4l2_ctrl *vflip; + struct v4l2_ctrl *hflip; + struct v4l2_ctrl *rotate; + } ctrls; unsigned int pending; unsigned int active; + bool rotate; } flip; struct vsp1_rwpf_memory mem; diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c index 5239e08fabc3..795a3ca9ca03 100644 --- a/drivers/media/platform/vsp1/vsp1_video.c +++ b/drivers/media/platform/vsp1/vsp1_video.c @@ -187,9 +187,13 @@ static void vsp1_video_pipeline_setup_partitions(struct vsp1_pipeline *pipe) struct vsp1_entity *entity; unsigned int div_size; + /* +* Partitions are computed on the size before rotation, use the format +* at the WPF sink. +*/ format = vsp1_entity_get_pad_format(&pipe->output->entity, pipe->output->entity.config, - RWPF_PAD_SOURCE); + RWPF_PAD_SINK); div_size = format->width; /* Gen2 hardware doesn't require image partitioning. */ @@ -229,9 +233,13 @@ static struct v4l2_rect vsp1_video_partition(struct vsp1_pipeline *pipe, struct v4l2_rect partition; unsigned int modulus; + /* +* Partitions are computed on the size before rotation, use the format +* at the WPF sink. +*/ format = vsp1_entity_get_pad_format(&pipe->output->entity, pipe->output->entity.config, - RWPF_PAD_SOURCE); + RWPF_PAD_SINK); /* A single partition simply processes the output size in full. */ if (pipe->partitions <= 1) { diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c index 25a2ed6e2e18..32df109b119f 100644 --- a/drivers/media/platform/vsp1/vsp1_wpf.c +++ b/drivers/media/platform/vsp1/vsp1_wpf.c @@ -43,32 +43,90 @@ static inline void vsp1_wpf_write(struct vsp1_rwpf *wpf, enum wpf_flip_ctrl { WPF_CTRL_VFLIP = 0, WPF_CTRL_HFLIP = 1, - WPF_CTRL_MAX, }; +static int vsp1_wpf_set_rotation(struct vsp1_rwpf *wpf, unsigned int rotation) +{ + struct vsp1_video *video = wpf->video; + struct v4l2_mbus_framefmt *sink_format; + struct v4l2_mbus_framefmt *source_format; + bool rotate; + int ret = 0; + + /* +* Only consider the 0°/180° from/to 90°/270° modifications, th
[GIT PULL FOR renesas-drivers] R-Car Gen3 HDMI output support
Hi Geert, Please find two pull requests below for renesas-drivers (in a single e-mail, lucky you :-)). The first tag contains driver changes only and is based on a merge of drm-next and drm-misc-next. The 5 patches from Maarten Lankhorst should be merged in drm-misc-next tomorrow (if all goes according to the plan). I'll rebase my tree on top of that, but that will only affect branches, not tags. More patches should also be merged in drm-misc-next in the next couple of days, I'll then send a pull request for the rest to Dave Airlie. In a few weeks I hope all of this to be in mainline. The second tag contains DT changes only and is based on Simon's latest devel branch. Nothing special there, it should just not make it to mainline before the driver changes get accepted. The following changes since commit 8d9874ba9561805fa7134c3371f8bf6b0650eb43: Merge remote-tracking branch 'drm-misc/drm-misc-next' into drm/next/base (2017-03-03 16:57:48 +0200) are available in the git repository at: git://linuxtv.org/pinchartl/media.git tags/drm-du-hdmi-v3-20170306 for you to fetch changes up to a429bed1995ed091f5b02c0b48405351a999fb14: drm: rcar-du: Add HDMI outputs to R8A7795 device description (2017-03-06 01:46:58 +0200) Jacopo Mondi (1): drm: rcar-du: Make sure the VSP is initialized on platforms that need it Kieran Bingham (2): drm: bridge: dw-hdmi: Add support for custom PHY configuration drm: bridge: dw-hdmi: Remove device type from platform data Koji Matsuoka (3): drm: rcar-du: Add Gen3 HDMI encoder support drm: rcar-du: Add DPLL support drm: rcar-du: Add HDMI outputs to R8A7795 device description Laurent Pinchart (30): drm: rcar-du: Switch to encoder .atomic_mode_set() helper function drm: rcar-du: Handle event when disabling CRTCs drm: rcar-du: Clear handled event pointer in CRTC state drm: rcar-du: Use DRM core's atomic commit helper devicetree/bindings: display: bridge: Add LVDS encoder DT bindings drm: bridge: Add LVDS encoder driver drm: bridge: vga-dac: Add adi,adv7123 compatible string drm: bridge: lvds-encoder: Add thine,thc63lvdm83d compatible string devicetree/bindings: display: Document common panel properties devicetree/bindings: display: Add bindings for LVDS panels devicetree/bindings: display: Add bindings for two Mitsubishi panels drm: Add data transmission order bus flag drm: panels: Add LVDS panel driver drm: rcar-du: Remove wait field from rcar_du_device structure drm: bridge: dw-hdmi: Remove unused functions drm: bridge: dw-hdmi: Move CSC configuration out of PHY code drm: bridge: dw-hdmi: Fix the PHY power down sequence drm: bridge: dw-hdmi: Fix the PHY power up sequence drm: bridge: dw-hdmi: Create PHY operations drm: bridge: dw-hdmi: Move the driver to a separate directory. Merge branch 'drm/next/lvds-encoder' into drm/du/base Merge branch 'drm/next/lvds-panel' into drm/du/base Merge branch 'drm/next/du' into drm/du/base Merge branch 'drm/next/dw-hdmi' (early part) into drm/du/base drm: rcar-du: Use the DRM panel API drm: rcar-du: Add support for LVDS mode selection drm: rcar-du: Replace manual bridge implementation with DRM bridge drm: rcar-du: Hardcode encoders types to DRM_MODE_ENCODER_NONE dt-bindings: display: renesas: Add R-Car Gen3 HDMI TX DT bindings drm: rcar-du: Skip disabled outputs Maarten Lankhorst (5): drm/atomic: Fix atomic helpers to use the new iterator macros, v3. drm/atomic: Make drm_atomic_plane_disabling easier to understand. drm/atomic: Add macros to access existing old/new state, v2. drm/atomic: Convert get_existing_state callers to get_old/new_state, v4. drm/blend: Use new atomic iterator macros. Neil Armstrong (2): drm: bridge: dw-hdmi: Enable CSC even for DVI drm: bridge: dw-hdmi: Switch to regmap for register access Wolfram Sang (1): drm: rcar-du: Don't open code of_device_get_match_data() .../bindings/display/bridge/lvds-transmitter.txt| 64 .../bindings/display/bridge/renesas,dw-hdmi.txt | 75 .../bindings/display/panel/mitsubishi,aa104xd12.txt | 47 +++ .../bindings/display/panel/mitsubishi,aa121td01.txt | 47 +++ .../devicetree/bindings/display/panel/panel-common.txt | 91 + .../devicetree/bindings/display/panel/panel-lvds.txt| 120 ++ MAINTAINERS | 1 + drivers/gpu/drm/bridge/Kconfig | 29 +- drivers/gpu/drm/bridge/Makefile | 5 +- drivers/gpu/drm/bridge/dumb-vga-dac.c | 1 + drivers/gpu/drm/bridge/lvds-encoder.c | 210 ++ drivers/gpu/drm/bridge/synopsys/Kconfig | 23 ++ drivers/gpu/drm/bridge/
[PATCH v3 2/5] arm64: dts: r8a7795: salvator-x: Enable HDMI outputs
From: Koji Matsuoka Instantiate the HDMI connectors and enable the encoders. Signed-off-by: Koji Matsuoka Signed-off-by: Ulrich Hecht Signed-off-by: Laurent Pinchart --- arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts | 50 ++ 1 file changed, 50 insertions(+) diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts index 7a8986edcdc0..e855e9572685 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts +++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts @@ -165,6 +165,30 @@ }; }; + hdmi0-out { + compatible = "hdmi-connector"; + label = "HDMI0 OUT"; + type = "a"; + + port { + hdmi0_con: endpoint { + remote-endpoint = <&rcar_dw_hdmi0_out>; + }; + }; + }; + + hdmi1-out { + compatible = "hdmi-connector"; + label = "HDMI1 OUT"; + type = "a"; + + port { + hdmi1_con: endpoint { + remote-endpoint = <&rcar_dw_hdmi1_out>; + }; + }; + }; + vga-encoder { compatible = "adi,adv7123"; @@ -198,6 +222,32 @@ }; }; +&hdmi0 { + status = "okay"; + + ports { + port@1 { + reg = <1>; + rcar_dw_hdmi0_out: endpoint { + remote-endpoint = <&hdmi0_con>; + }; + }; + }; +}; + +&hdmi1 { + status = "okay"; + + ports { + port@1 { + reg = <1>; + rcar_dw_hdmi1_out: endpoint { + remote-endpoint = <&hdmi1_con>; + }; + }; + }; +}; + &du { pinctrl-0 = <&du_pins>; pinctrl-names = "default"; -- Regards, Laurent Pinchart
[PATCH v3 1/5] arm64: dts: r8a7795: Add HDMI encoder support
From: Ulrich Hecht Add DT nodes for the two HDMI encoders in disabled state. Based on work by Koji Matsuoka. Signed-off-by: Ulrich Hecht Signed-off-by: Laurent Pinchart --- arch/arm64/boot/dts/renesas/r8a7795.dtsi | 50 1 file changed, 50 insertions(+) diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi index eac4f29aa5cd..0887cc6b1f6c 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi @@ -1637,11 +1637,13 @@ port@1 { reg = <1>; du_out_hdmi0: endpoint { + remote-endpoint = <&dw_hdmi0_in>; }; }; port@2 { reg = <2>; du_out_hdmi1: endpoint { + remote-endpoint = <&dw_hdmi1_in>; }; }; port@3 { @@ -1709,5 +1711,53 @@ }; }; }; + + hdmi0: hdmi0@fead { + compatible = "renesas,r8a7795-hdmi", "renesas,rcar-gen3-hdmi"; + reg = <0 0xfead 0 0x1>; + interrupts = <0 389 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 729>, <&cpg CPG_CORE R8A7795_CLK_HDMI>; + clock-names = "iahb", "isfr"; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + dw_hdmi0_in: endpoint { + remote-endpoint = <&du_out_hdmi0>; + }; + }; + port@1 { + reg = <1>; + }; + }; + }; + + hdmi1: hdmi1@feae { + compatible = "renesas,r8a7795-hdmi", "renesas,rcar-gen3-hdmi"; + reg = <0 0xfeae 0 0x1>; + interrupts = <0 436 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 728>, <&cpg CPG_CORE R8A7795_CLK_HDMI>; + clock-names = "iahb", "isfr"; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + dw_hdmi1_in: endpoint { + remote-endpoint = <&du_out_hdmi1>; + }; + }; + port@1 { + reg = <1>; + }; + }; + }; }; }; -- Regards, Laurent Pinchart
[PATCH v3 5/5] ARM: shmobile: dts: Switch to panel-lvds bindings for Mitsubishi panels
The aa104xd12 and aa121td01 panels are LVDS panels, not DPI panels. Use the correct DT bindings. Signed-off-by: Laurent Pinchart --- arch/arm/boot/dts/r8a77xx-aa104xd12-panel.dtsi | 3 ++- arch/arm/boot/dts/r8a77xx-aa121td01-panel.dtsi | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/r8a77xx-aa104xd12-panel.dtsi b/arch/arm/boot/dts/r8a77xx-aa104xd12-panel.dtsi index 65cb50f0c29f..238d14bb0ebe 100644 --- a/arch/arm/boot/dts/r8a77xx-aa104xd12-panel.dtsi +++ b/arch/arm/boot/dts/r8a77xx-aa104xd12-panel.dtsi @@ -10,10 +10,11 @@ / { panel { - compatible = "mitsubishi,aa104xd12", "panel-dpi"; + compatible = "mitsubishi,aa104xd12", "panel-lvds"; width-mm = <210>; height-mm = <158>; + data-mapping = "jeida-18"; panel-timing { /* 1024x768 @65Hz */ diff --git a/arch/arm/boot/dts/r8a77xx-aa121td01-panel.dtsi b/arch/arm/boot/dts/r8a77xx-aa121td01-panel.dtsi index a07ebf8f6938..04aafd479775 100644 --- a/arch/arm/boot/dts/r8a77xx-aa121td01-panel.dtsi +++ b/arch/arm/boot/dts/r8a77xx-aa121td01-panel.dtsi @@ -10,10 +10,11 @@ / { panel { - compatible = "mitsubishi,aa121td01", "panel-dpi"; + compatible = "mitsubishi,aa121td01", "panel-lvds"; width-mm = <261>; height-mm = <163>; + data-mapping = "jeida-18"; panel-timing { /* 1280x800 @60Hz */ -- Regards, Laurent Pinchart
[PATCH v3 3/5] arm64: dts: r8a7795: salvator-x: Add DU1 and DU2 external dot clocks
The DU1 and DU2 external dot clocks are fixed frequency clock generators running at 33MHz. Signed-off-by: Laurent Pinchart --- arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts | 23 ++ 1 file changed, 23 insertions(+) diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts index e855e9572685..77a66568eb3f 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts +++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts @@ -165,6 +165,19 @@ }; }; + /* External DU dot clocks */ + x21_clk: x21-clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <3300>; + }; + + x22_clk: x22-clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <3300>; + }; + hdmi0-out { compatible = "hdmi-connector"; label = "HDMI0 OUT"; @@ -253,6 +266,16 @@ pinctrl-names = "default"; status = "okay"; + clocks = <&cpg CPG_MOD 724>, +<&cpg CPG_MOD 723>, +<&cpg CPG_MOD 722>, +<&cpg CPG_MOD 721>, +<&cpg CPG_MOD 727>, +<&x21_clk>, +<&x22_clk>; + clock-names = "du.0", "du.1", "du.2", "du.3", "lvds.0", + "dclkin.1", "dclkin.2"; + ports { port@0 { endpoint { -- Regards, Laurent Pinchart
[PATCH v3 4/5] arm64: dts: r8a7795: salvator-x: Add DU0 and DU3 external dot clocks
The clocks are generated by an I2C-controlled programmable clock generator. Signed-off-by: Laurent Pinchart Reviewed-by: Marek Vasut Reviewed-by: Geert Uytterhoeven --- arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts | 26 -- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts index 77a66568eb3f..01f395513715 100644 --- a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts +++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts @@ -178,6 +178,12 @@ clock-frequency = <3300>; }; + x23_clk: x23-clock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <2500>; + }; + hdmi0-out { compatible = "hdmi-connector"; label = "HDMI0 OUT"; @@ -271,10 +277,12 @@ <&cpg CPG_MOD 722>, <&cpg CPG_MOD 721>, <&cpg CPG_MOD 727>, +<&versaclock5 1>, <&x21_clk>, -<&x22_clk>; +<&x22_clk>, +<&versaclock5 2>; clock-names = "du.0", "du.1", "du.2", "du.3", "lvds.0", - "dclkin.1", "dclkin.2"; + "dclkin.0", "dclkin.1", "dclkin.2", "dclkin.3"; ports { port@0 { @@ -460,6 +468,20 @@ }; }; +&i2c4 { + status = "okay"; + + clock-frequency = <10>; + + versaclock5: clock-generator@6a { + compatible = "idt,5p49v5923"; + reg = <0x6a>; + #clock-cells = <1>; + clocks = <&x23_clk>; + clock-names = "xin"; + }; +}; + &rcar_sound { pinctrl-0 = <&sound_pins &sound_clk_pins>; pinctrl-names = "default"; -- Regards, Laurent Pinchart
[PATCH v3 0/5] R-Car H3 HDMI output DT integration
Hello, This patch series contains all the DT changes needed to integrate HDMI output support for the H3 Salvator-X board. The patches have previously been posted as part of other patch series with driver changes. They are now submitted standalone as I expect the driver patches to be merged soon. Simon, please refrain from merging this for now, I will give you a green light once the driver gets accepted. For convenience, the patches are available from git://linuxtv.org/pinchartl/media.git drm-next-dt-v3-20170306 Koji Matsuoka (1): arm64: dts: r8a7795: salvator-x: Enable HDMI outputs Laurent Pinchart (3): arm64: dts: r8a7795: salvator-x: Add DU1 and DU2 external dot clocks arm64: dts: r8a7795: salvator-x: Add DU0 and DU3 external dot clocks ARM: shmobile: dts: Switch to panel-lvds bindings for Mitsubishi panels Ulrich Hecht (1): arm64: dts: r8a7795: Add HDMI encoder support arch/arm/boot/dts/r8a77xx-aa104xd12-panel.dtsi | 3 +- arch/arm/boot/dts/r8a77xx-aa121td01-panel.dtsi | 3 +- arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts | 95 ++ arch/arm64/boot/dts/renesas/r8a7795.dtsi | 50 4 files changed, 149 insertions(+), 2 deletions(-) -- Regards, Laurent Pinchart
[PATCH v3 5/9] dt-bindings: display: renesas: Add R-Car Gen3 HDMI TX DT bindings
The Renesas R-Car Gen3 SoCs use a Synopsys DWC HDMI TX encoder IP. Add corresponding device tree bindings based on the DWC HDMI TX bindings model. Signed-off-by: Laurent Pinchart Acked-by: Rob Herring --- .../bindings/display/bridge/renesas,dw-hdmi.txt| 75 ++ MAINTAINERS| 1 + 2 files changed, 76 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt b/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt new file mode 100644 index ..f6b3f36d422b --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt @@ -0,0 +1,75 @@ +Renesas Gen3 DWC HDMI TX Encoder + + +The HDMI transmitter is a Synopsys DesignWare HDMI 1.4 TX controller IP +with a companion PHY IP. + +These DT bindings follow the Synopsys DWC HDMI TX bindings defined in +Documentation/devicetree/bindings/display/bridge/dw_hdmi.txt with the +following device-specific properties. + + +Required properties: + +- compatible : Shall contain one or more of + - "renesas,r8a7795-hdmi" for R8A7795 (R-Car H3) compatible HDMI TX + - "renesas,rcar-gen3-hdmi" for the generic R-Car Gen3 compatible HDMI TX + +When compatible with generic versions, nodes must list the SoC-specific +version corresponding to the platform first, followed by the +family-specific version. + +- reg: See dw_hdmi.txt. +- interrupts: HDMI interrupt number +- clocks: See dw_hdmi.txt. +- clock-names: Shall contain "iahb" and "isfr" as defined in dw_hdmi.txt. +- ports: See dw_hdmi.txt. The DWC HDMI shall have one port numbered 0 + corresponding to the video input of the controller and one port numbered 1 + corresponding to its HDMI output. Each port shall have a single endpoint. + +Optional properties: + +- power-domains: Shall reference the power domain that contains the DWC HDMI, + if any. + + +Example: + + hdmi0: hdmi0@fead { + compatible = "renesas,r8a7795-dw-hdmi"; + reg = <0 0xfead 0 0x1>; + interrupts = <0 389 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_CORE R8A7795_CLK_S0D4>, <&cpg CPG_MOD 729>; + clock-names = "iahb", "isfr"; + power-domains = <&sysc R8A7795_PD_ALWAYS_ON>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + dw_hdmi0_in: endpoint { + remote-endpoint = <&du_out_hdmi0>; + }; + }; + port@1 { + reg = <1>; + rcar_dw_hdmi0_out: endpoint { + remote-endpoint = <&hdmi0_con>; + }; + }; + }; + }; + + hdmi0-out { + compatible = "hdmi-connector"; + label = "HDMI0 OUT"; + type = "a"; + + port { + hdmi0_con: endpoint { + remote-endpoint = <&rcar_dw_hdmi0_out>; + }; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 6ba488e6c958..40d704105957 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4382,6 +4382,7 @@ S:Supported F: drivers/gpu/drm/rcar-du/ F: drivers/gpu/drm/shmobile/ F: include/linux/platform_data/shmob_drm.h +F: Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt F: Documentation/devicetree/bindings/display/renesas,du.txt DRM DRIVER FOR QXL VIRTUAL GPU -- Regards, Laurent Pinchart
[PATCH v3 9/9] drm: rcar-du: Add HDMI outputs to R8A7795 device description
From: Koji Matsuoka Update the device description with the two available HDMI outputs. Signed-off-by: Koji Matsuoka Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 4 +++- drivers/gpu/drm/rcar-du/rcar_du_drv.c | 12 ++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h index a7194812997e..15871fae7445 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h @@ -1,7 +1,7 @@ /* * rcar_du_crtc.h -- R-Car Display Unit CRTCs * - * Copyright (C) 2013-2014 Renesas Electronics Corporation + * Copyright (C) 2013-2015 Renesas Electronics Corporation * * Contact: Laurent Pinchart (laurent.pinch...@ideasonboard.com) * @@ -61,6 +61,8 @@ enum rcar_du_output { RCAR_DU_OUTPUT_DPAD1, RCAR_DU_OUTPUT_LVDS0, RCAR_DU_OUTPUT_LVDS1, + RCAR_DU_OUTPUT_HDMI0, + RCAR_DU_OUTPUT_HDMI1, RCAR_DU_OUTPUT_TCON, RCAR_DU_OUTPUT_MAX, }; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index 3d789e68ec13..846971fdc196 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -149,13 +149,21 @@ static const struct rcar_du_device_info rcar_du_r8a7795_info = { | RCAR_DU_FEATURE_VSP1_SOURCE, .num_crtcs = 4, .routes = { - /* R8A7795 has one RGB output, one LVDS output and two -* (currently unsupported) HDMI outputs. + /* R8A7795 has one RGB output, two HDMI outputs and one +* LVDS output. */ [RCAR_DU_OUTPUT_DPAD0] = { .possible_crtcs = BIT(3), .port = 0, }, + [RCAR_DU_OUTPUT_HDMI0] = { + .possible_crtcs = BIT(1), + .port = 1, + }, + [RCAR_DU_OUTPUT_HDMI1] = { + .possible_crtcs = BIT(2), + .port = 2, + }, [RCAR_DU_OUTPUT_LVDS0] = { .possible_crtcs = BIT(0), .port = 3, -- Regards, Laurent Pinchart
[PATCH v3 7/9] drm: rcar-du: Skip disabled outputs
When a DT node connected to a DU output is disabled no bridge will ever be instantiated for it. Skip the output in that case. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index f38fc2f3f93d..f4125c8ca902 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -302,6 +302,13 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu, return -ENODEV; } + if (!of_device_is_available(entity)) { + dev_dbg(rcdu->dev, + "connected entity %s is disabled, skipping\n", + entity->full_name); + return -ENODEV; + } + entity_ep_node = of_parse_phandle(ep->local_node, "remote-endpoint", 0); for_each_endpoint_of_node(entity, ep_node) { -- Regards, Laurent Pinchart
[PATCH v3 6/9] drm: rcar-du: Add Gen3 HDMI encoder support
From: Koji Matsuoka The R-Car Gen3 SoCs include on-chip DesignWare HDMI encoders. Support them with a platform driver to provide platform glue data to the dw-hdmi driver. The driver is a complete rewrite of code coming from the Renesas BSP, save for the values in the PHY parameters table. Signed-off-by: Koji Matsuoka Signed-off-by: Ulrich Hecht Signed-off-by: Laurent Pinchart Signed-off-by: Kieran Bingham --- Changes since v2: - Replaced the dependency on DRM_RCAR_DU with DRM and made the symbol tristate. --- drivers/gpu/drm/rcar-du/Kconfig| 7 +++ drivers/gpu/drm/rcar-du/Makefile | 1 + drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c | 100 + 3 files changed, 108 insertions(+) create mode 100644 drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig index 06121eeba9e5..8a50dab19e5c 100644 --- a/drivers/gpu/drm/rcar-du/Kconfig +++ b/drivers/gpu/drm/rcar-du/Kconfig @@ -11,6 +11,13 @@ config DRM_RCAR_DU Choose this option if you have an R-Car chipset. If M is selected the module will be called rcar-du-drm. +config DRM_RCAR_DW_HDMI + tristate "R-Car DU Gen3 HDMI Encoder Support" + depends on DRM && OF + select DRM_DW_HDMI + help + Enable support for R-Car Gen3 internal HDMI encoder. + config DRM_RCAR_LVDS bool "R-Car DU LVDS Encoder Support" depends on DRM_RCAR_DU diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile index a492e6858691..2131e722de3b 100644 --- a/drivers/gpu/drm/rcar-du/Makefile +++ b/drivers/gpu/drm/rcar-du/Makefile @@ -11,3 +11,4 @@ rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS) += rcar_du_lvdsenc.o rcar-du-drm-$(CONFIG_DRM_RCAR_VSP) += rcar_du_vsp.o obj-$(CONFIG_DRM_RCAR_DU) += rcar-du-drm.o +obj-$(CONFIG_DRM_RCAR_DW_HDMI) += rcar_dw_hdmi.o diff --git a/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c new file mode 100644 index ..7539626b8ebd --- /dev/null +++ b/drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c @@ -0,0 +1,100 @@ +/* + * R-Car Gen3 HDMI PHY + * + * Copyright (C) 2016 Renesas Electronics Corporation + * + * Contact: Laurent Pinchart (laurent.pinch...@ideasonboard.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include + +#include + +#define RCAR_HDMI_PHY_OPMODE_PLLCFG0x06/* Mode of operation and PLL dividers */ +#define RCAR_HDMI_PHY_PLLCURRGMPCTRL 0x10/* PLL current and Gmp (conductance) */ +#define RCAR_HDMI_PHY_PLLDIVCTRL 0x11/* PLL dividers */ + +struct rcar_hdmi_phy_params { + unsigned long mpixelclock; + u16 opmode_div; /* Mode of operation and PLL dividers */ + u16 curr_gmp; /* PLL current and Gmp (conductance) */ + u16 div;/* PLL dividers */ +}; + +static const struct rcar_hdmi_phy_params rcar_hdmi_phy_params[] = { + { 3550, 0x0003, 0x0344, 0x0328 }, + { 4490, 0x0003, 0x0285, 0x0128 }, + { 7100, 0x0002, 0x1184, 0x0314 }, + { 9000, 0x0002, 0x1144, 0x0114 }, + { 14025, 0x0001, 0x20c4, 0x030a }, + { 18275, 0x0001, 0x2084, 0x010a }, + { 28125, 0x, 0x0084, 0x0305 }, + { 29700, 0x, 0x0084, 0x0105 }, + { ~0UL, 0x, 0x, 0x }, +}; + +static int rcar_hdmi_phy_configure(struct dw_hdmi *hdmi, + const struct dw_hdmi_plat_data *pdata, + unsigned long mpixelclock) +{ + const struct rcar_hdmi_phy_params *params = rcar_hdmi_phy_params; + + for (; params && params->mpixelclock != ~0UL; ++params) { + if (mpixelclock <= params->mpixelclock) + break; + } + + if (params->mpixelclock == ~0UL) + return -EINVAL; + + dw_hdmi_phy_i2c_write(hdmi, params->opmode_div, + RCAR_HDMI_PHY_OPMODE_PLLCFG); + dw_hdmi_phy_i2c_write(hdmi, params->curr_gmp, + RCAR_HDMI_PHY_PLLCURRGMPCTRL); + dw_hdmi_phy_i2c_write(hdmi, params->div, RCAR_HDMI_PHY_PLLDIVCTRL); + + return 0; +} + +static const struct dw_hdmi_plat_data rcar_dw_hdmi_plat_data = { + .configure_phy = rcar_hdmi_phy_configure, +}; + +static int rcar_dw_hdmi_probe(struct platform_device *pdev) +{ + return dw_hdmi_probe(pdev, &rcar_dw_hdmi_plat_data); +} + +static int rcar_dw_hdmi_remove(struct platform_device *pdev) +{ + dw_hdmi_remove(pdev); + + return 0; +} + +static const struct of_device_id rcar_dw_hdmi_of_table[] = { + { .compatible = "renesas,rcar-gen3-hdmi" }, + { /* Sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, rcar_dw_hdmi_
[PATCH v3 8/9] drm: rcar-du: Add DPLL support
From: Koji Matsuoka The implementation hardcodes a workaround for the H3 ES1.x SoC regardless of the SoC revision, as the workaround can be safely applied on all devices in the Gen3 family without any side effect. Signed-off-by: Koji Matsuoka Signed-off-by: Ulrich Hecht Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 81 +- drivers/gpu/drm/rcar-du/rcar_du_drv.c | 1 + drivers/gpu/drm/rcar-du/rcar_du_drv.h | 1 + drivers/gpu/drm/rcar-du/rcar_du_regs.h | 23 ++ 4 files changed, 105 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 7391dd95c733..4ed6f2340af0 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -106,9 +106,62 @@ static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc) * Hardware Setup */ +struct dpll_info { + unsigned int output; + unsigned int fdpll; + unsigned int n; + unsigned int m; +}; + +static void rcar_du_dpll_divider(struct rcar_du_crtc *rcrtc, +struct dpll_info *dpll, +unsigned long input, +unsigned long target) +{ + unsigned long best_diff = (unsigned long)-1; + unsigned long diff; + unsigned int fdpll; + unsigned int m; + unsigned int n; + + for (n = 39; n < 120; n++) { + for (m = 0; m < 4; m++) { + for (fdpll = 1; fdpll < 32; fdpll++) { + unsigned long output; + + /* 1/2 (FRQSEL=1) for duty rate 50% */ + output = input * (n + 1) / (m + 1) + / (fdpll + 1) / 2; + + if (output >= 4) + continue; + + diff = abs((long)output - (long)target); + if (best_diff > diff) { + best_diff = diff; + dpll->n = n; + dpll->m = m; + dpll->fdpll = fdpll; + dpll->output = output; + } + + if (diff == 0) + goto done; + } + } + } + +done: + dev_dbg(rcrtc->group->dev->dev, + "output:%u, fdpll:%u, n:%u, m:%u, diff:%lu\n", +dpll->output, dpll->fdpll, dpll->n, dpll->m, +best_diff); +} + static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc) { const struct drm_display_mode *mode = &rcrtc->crtc.state->adjusted_mode; + struct rcar_du_device *rcdu = rcrtc->group->dev; unsigned long mode_clock = mode->clock * 1000; unsigned long clk; u32 value; @@ -124,12 +177,18 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc) escr = div | ESCR_DCLKSEL_CLKS; if (rcrtc->extclock) { + struct dpll_info dpll = { 0 }; unsigned long extclk; unsigned long extrate; unsigned long rate; u32 extdiv; extclk = clk_get_rate(rcrtc->extclock); + if (rcdu->info->dpll_ch & (1 << rcrtc->index)) { + rcar_du_dpll_divider(rcrtc, &dpll, extclk, mode_clock); + extclk = dpll.output; + } + extdiv = DIV_ROUND_CLOSEST(extclk, mode_clock); extdiv = clamp(extdiv, 1U, 64U) - 1; @@ -140,7 +199,27 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc) abs((long)rate - (long)mode_clock)) { dev_dbg(rcrtc->group->dev->dev, "crtc%u: using external clock\n", rcrtc->index); - escr = extdiv | ESCR_DCLKSEL_DCLKIN; + + if (rcdu->info->dpll_ch & (1 << rcrtc->index)) { + u32 dpllcr = DPLLCR_CODE | DPLLCR_CLKE + | DPLLCR_FDPLL(dpll.fdpll) + | DPLLCR_N(dpll.n) | DPLLCR_M(dpll.m) + | DPLLCR_STBY; + + if (rcrtc->index == 1) + dpllcr |= DPLLCR_PLCS1 + | DPLLCR_INCS_DOTCLKIN1; + else + dpllcr |= DPLLCR_PLCS0 + | DPLLCR_INCS_DOTCLKIN0; + + rcar_du_group_write(rcrtc->group, DPLLCR, +
[PATCH v3 4/9] drm: rcar-du: Hardcode encoders types to DRM_MODE_ENCODER_NONE
Unlike the connector type, the encoder type is unused by userspace. As it is equally unused in the driver, except in a single location where the connector type can be used instead, hardcode it to DRM_MODE_ENCODER_NONE. This allow removing all code that tries to determine (unsuccessfully in case a bridge is used) the encoder type. Signed-off-by: Laurent Pinchart --- Changes since v3: - New patch, replaces "drm: rcar-du: Initialize encoder's type based on the bridge's type" --- drivers/gpu/drm/rcar-du/rcar_du_drv.c | 15 - drivers/gpu/drm/rcar-du/rcar_du_drv.h | 2 -- drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 30 - drivers/gpu/drm/rcar-du/rcar_du_encoder.h | 9 drivers/gpu/drm/rcar-du/rcar_du_kms.c | 37 ++- 5 files changed, 11 insertions(+), 82 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index eb905e6b5f4c..327adb7a25c4 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -44,12 +44,10 @@ static const struct rcar_du_device_info rcar_du_r8a7779_info = { */ [RCAR_DU_OUTPUT_DPAD0] = { .possible_crtcs = BIT(0), - .encoder_type = DRM_MODE_ENCODER_NONE, .port = 0, }, [RCAR_DU_OUTPUT_DPAD1] = { .possible_crtcs = BIT(1) | BIT(0), - .encoder_type = DRM_MODE_ENCODER_NONE, .port = 1, }, }, @@ -68,17 +66,14 @@ static const struct rcar_du_device_info rcar_du_r8a7790_info = { */ [RCAR_DU_OUTPUT_DPAD0] = { .possible_crtcs = BIT(2) | BIT(1) | BIT(0), - .encoder_type = DRM_MODE_ENCODER_NONE, .port = 0, }, [RCAR_DU_OUTPUT_LVDS0] = { .possible_crtcs = BIT(0), - .encoder_type = DRM_MODE_ENCODER_LVDS, .port = 1, }, [RCAR_DU_OUTPUT_LVDS1] = { .possible_crtcs = BIT(2) | BIT(1), - .encoder_type = DRM_MODE_ENCODER_LVDS, .port = 2, }, }, @@ -97,12 +92,10 @@ static const struct rcar_du_device_info rcar_du_r8a7791_info = { */ [RCAR_DU_OUTPUT_DPAD0] = { .possible_crtcs = BIT(1) | BIT(0), - .encoder_type = DRM_MODE_ENCODER_NONE, .port = 0, }, [RCAR_DU_OUTPUT_LVDS0] = { .possible_crtcs = BIT(0), - .encoder_type = DRM_MODE_ENCODER_LVDS, .port = 1, }, }, @@ -118,12 +111,10 @@ static const struct rcar_du_device_info rcar_du_r8a7792_info = { /* R8A7792 has two RGB outputs. */ [RCAR_DU_OUTPUT_DPAD0] = { .possible_crtcs = BIT(0), - .encoder_type = DRM_MODE_ENCODER_NONE, .port = 0, }, [RCAR_DU_OUTPUT_DPAD1] = { .possible_crtcs = BIT(1), - .encoder_type = DRM_MODE_ENCODER_NONE, .port = 1, }, }, @@ -141,12 +132,10 @@ static const struct rcar_du_device_info rcar_du_r8a7794_info = { */ [RCAR_DU_OUTPUT_DPAD0] = { .possible_crtcs = BIT(0), - .encoder_type = DRM_MODE_ENCODER_NONE, .port = 0, }, [RCAR_DU_OUTPUT_DPAD1] = { .possible_crtcs = BIT(1), - .encoder_type = DRM_MODE_ENCODER_NONE, .port = 1, }, }, @@ -165,12 +154,10 @@ static const struct rcar_du_device_info rcar_du_r8a7795_info = { */ [RCAR_DU_OUTPUT_DPAD0] = { .possible_crtcs = BIT(3), - .encoder_type = DRM_MODE_ENCODER_NONE, .port = 0, }, [RCAR_DU_OUTPUT_LVDS0] = { .possible_crtcs = BIT(0), - .encoder_type = DRM_MODE_ENCODER_LVDS, .port = 3, }, }, @@ -189,12 +176,10 @@ static const struct rcar_du_device_info rcar_du_r8a7796_info = { */ [RCAR_DU_OUTPUT_DPAD0] = { .possible_crtcs = BIT(2), - .encoder_type = DRM_MODE_ENCODER_NONE, .port = 0, }, [RCAR_DU_OUTPUT_LVDS0] = { .possible_crtcs =
[PATCH v3 0/9] R-Car Gen3 HDMI output support
Hello, This patch series implements support for the HDMI output on Renesas R-Car Gen3 SoCs, and more specifically on the R-Car H3. Compared to the previous version, I've left out all the dw-hdmi patches that have been updated separately and are on their way to being merged. I've also left out the DT integration patches that will be submitted separately. I have on the other hand included patches 1/9 to 4/9 that were an implicit dependency of the previous version. The patches are based on a merge of the following branches and tags from git://linuxtv.org/pinchartl/media.git - DWC HDMI Driver: drm-next-dw-hdmi-v5.1-20170306 - DRM LVDS Encoder Driver: drm-next-lvds-encoder-v4-20170302 - DRM LVDS Panel Driver: drm/next/lvds-panel - R-Car DU Driver: drm/next/du I plan to send a pull request for theses patches and the dependencies that won't be merged through drm-misc in the next few days. Koji Matsuoka (3): drm: rcar-du: Add Gen3 HDMI encoder support drm: rcar-du: Add DPLL support drm: rcar-du: Add HDMI outputs to R8A7795 device description Laurent Pinchart (6): drm: rcar-du: Use the DRM panel API drm: rcar-du: Add support for LVDS mode selection drm: rcar-du: Replace manual bridge implementation with DRM bridge drm: rcar-du: Hardcode encoders types to DRM_MODE_ENCODER_NONE dt-bindings: display: renesas: Add R-Car Gen3 HDMI TX DT bindings drm: rcar-du: Skip disabled outputs .../bindings/display/bridge/renesas,dw-hdmi.txt| 75 + MAINTAINERS| 1 + drivers/gpu/drm/rcar-du/Kconfig| 10 +- drivers/gpu/drm/rcar-du/Makefile | 6 +- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 81 +- drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 4 +- drivers/gpu/drm/rcar-du/rcar_du_drv.c | 28 ++-- drivers/gpu/drm/rcar-du/rcar_du_drv.h | 3 +- drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 179 + drivers/gpu/drm/rcar-du/rcar_du_encoder.h | 14 +- drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c | 134 --- drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h | 35 drivers/gpu/drm/rcar-du/rcar_du_kms.c | 44 ++--- drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c | 68 +++- drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c | 11 +- drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h | 13 ++ drivers/gpu/drm/rcar-du/rcar_du_regs.h | 23 +++ drivers/gpu/drm/rcar-du/rcar_du_vgacon.c | 82 -- drivers/gpu/drm/rcar-du/rcar_du_vgacon.h | 23 --- drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c | 100 20 files changed, 475 insertions(+), 459 deletions(-) create mode 100644 Documentation/devicetree/bindings/display/bridge/renesas,dw-hdmi.txt delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vgacon.c delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vgacon.h create mode 100644 drivers/gpu/drm/rcar-du/rcar_dw_hdmi.c -- Regards, Laurent Pinchart
[PATCH v3 2/9] drm: rcar-du: Add support for LVDS mode selection
Retrieve the LVDS mode from the panel and configure the LVDS encoder accordingly. LVDS mode selection is static as LVDS panels can't be hot-plugged on any of the device supported by the driver. Support for dynamic mode selection can be implemented in the future when needed. Signed-off-by: Laurent Pinchart --- Changes since v2: - Rebased on top of the DRM_BUS_FLAG_DATA_MIRROR rename. --- drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 27 +++ drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c | 11 +-- drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h | 13 + 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c index 31f878ad099d..3a3c9374794e 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c @@ -98,6 +98,8 @@ static void rcar_du_encoder_mode_set(struct drm_encoder *encoder, struct drm_connector_state *conn_state) { struct rcar_du_encoder *renc = to_rcar_encoder(encoder); + struct drm_display_info *info = &conn_state->connector->display_info; + enum rcar_lvds_mode mode; rcar_du_crtc_route_output(crtc_state->crtc, renc->output); @@ -111,6 +113,31 @@ static void rcar_du_encoder_mode_set(struct drm_encoder *encoder, } renc->connector = to_rcar_connector(conn_state->connector); + + if (!info->num_bus_formats || !info->bus_formats) { + dev_err(encoder->dev->dev, "no LVDS bus format reported\n"); + return; + } + + switch (info->bus_formats[0]) { + case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: + case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: + mode = RCAR_LVDS_MODE_JEIDA; + break; + case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: + mode = RCAR_LVDS_MODE_VESA; + break; + default: + dev_err(encoder->dev->dev, + "unsupported LVDS bus format 0x%04x\n", + info->bus_formats[0]); + return; + } + + if (info->bus_flags & DRM_BUS_FLAG_DATA_LSB_TO_MSB) + mode |= RCAR_LVDS_MODE_MIRROR; + + rcar_du_lvdsenc_set_mode(renc->lvds, mode); } static const struct drm_encoder_helper_funcs encoder_helper_funcs = { diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c index e3a4985f6f3f..1661f6201210 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c @@ -31,6 +31,7 @@ struct rcar_du_lvdsenc { bool enabled; enum rcar_lvds_input input; + enum rcar_lvds_mode mode; }; static void rcar_lvds_write(struct rcar_du_lvdsenc *lvds, u32 reg, u32 data) @@ -61,7 +62,7 @@ static void rcar_du_lvdsenc_start_gen2(struct rcar_du_lvdsenc *lvds, /* Select the input, hardcode mode 0, enable LVDS operation and turn * bias circuitry on. */ - lvdcr0 = LVDCR0_BEN | LVDCR0_LVEN; + lvdcr0 = (lvds->mode << LVDCR0_LVMD_SHIFT) | LVDCR0_BEN | LVDCR0_LVEN; if (rcrtc->index == 2) lvdcr0 |= LVDCR0_DUSEL; rcar_lvds_write(lvds, LVDCR0, lvdcr0); @@ -114,7 +115,7 @@ static void rcar_du_lvdsenc_start_gen3(struct rcar_du_lvdsenc *lvds, * Turn the PLL on, set it to LVDS normal mode, wait for the startup * delay and turn the output on. */ - lvdcr0 = LVDCR0_PLLON; + lvdcr0 = (lvds->mode << LVDCR0_LVMD_SHIFT) | LVDCR0_PLLON; rcar_lvds_write(lvds, LVDCR0, lvdcr0); lvdcr0 |= LVDCR0_PWD; @@ -211,6 +212,12 @@ void rcar_du_lvdsenc_atomic_check(struct rcar_du_lvdsenc *lvds, mode->clock = clamp(mode->clock, 25175, 148500); } +void rcar_du_lvdsenc_set_mode(struct rcar_du_lvdsenc *lvds, + enum rcar_lvds_mode mode) +{ + lvds->mode = mode; +} + static int rcar_du_lvdsenc_get_resources(struct rcar_du_lvdsenc *lvds, struct platform_device *pdev) { diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h index dfdba746edf4..7218ac89333e 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.h @@ -26,8 +26,17 @@ enum rcar_lvds_input { RCAR_LVDS_INPUT_DU2, }; +/* Keep in sync with the LVDCR0.LVMD hardware register values. */ +enum rcar_lvds_mode { + RCAR_LVDS_MODE_JEIDA = 0, + RCAR_LVDS_MODE_MIRROR = 1, + RCAR_LVDS_MODE_VESA = 4, +}; + #if IS_ENABLED(CONFIG_DRM_RCAR_LVDS) int rcar_du_lvdsenc_init(struct rcar_du_device *rcdu); +void rcar_du_lvdsenc_set_mode(struct rcar_du_lvdsenc *lvds, + enum rcar_lvds_mode mode); int rcar_du_lvdsenc_enable(struct rcar_du_lvdsenc *lvds, struct drm_crtc *crtc, bool enable); void
[PATCH v3 1/9] drm: rcar-du: Use the DRM panel API
Instead of parsing the panel device tree node manually, use the panel API to delegate panel handling to a panel driver. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/Kconfig | 1 + drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 22 ++ drivers/gpu/drm/rcar-du/rcar_du_encoder.h | 3 ++ drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c | 68 +++ 4 files changed, 50 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig index 4c2fd056dd6d..2bab449add76 100644 --- a/drivers/gpu/drm/rcar-du/Kconfig +++ b/drivers/gpu/drm/rcar-du/Kconfig @@ -20,6 +20,7 @@ config DRM_RCAR_HDMI config DRM_RCAR_LVDS bool "R-Car DU LVDS Encoder Support" depends on DRM_RCAR_DU + select DRM_PANEL help Enable support for the R-Car Display Unit embedded LVDS encoders. diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c index 3974d9495f37..31f878ad099d 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "rcar_du_drv.h" #include "rcar_du_encoder.h" @@ -33,6 +34,11 @@ static void rcar_du_encoder_disable(struct drm_encoder *encoder) { struct rcar_du_encoder *renc = to_rcar_encoder(encoder); + if (renc->connector && renc->connector->panel) { + drm_panel_disable(renc->connector->panel); + drm_panel_unprepare(renc->connector->panel); + } + if (renc->lvds) rcar_du_lvdsenc_enable(renc->lvds, encoder->crtc, false); } @@ -43,6 +49,11 @@ static void rcar_du_encoder_enable(struct drm_encoder *encoder) if (renc->lvds) rcar_du_lvdsenc_enable(renc->lvds, encoder->crtc, true); + + if (renc->connector && renc->connector->panel) { + drm_panel_prepare(renc->connector->panel); + drm_panel_enable(renc->connector->panel); + } } static int rcar_du_encoder_atomic_check(struct drm_encoder *encoder, @@ -89,6 +100,17 @@ static void rcar_du_encoder_mode_set(struct drm_encoder *encoder, struct rcar_du_encoder *renc = to_rcar_encoder(encoder); rcar_du_crtc_route_output(crtc_state->crtc, renc->output); + + if (!renc->lvds) { + /* +* The DU driver creates connectors only for the outputs of the +* internal LVDS encoders. +*/ + renc->connector = NULL; + return; + } + + renc->connector = to_rcar_connector(conn_state->connector); } static const struct drm_encoder_helper_funcs encoder_helper_funcs = { diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h index a050a3699857..b79b2f075a74 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h @@ -17,6 +17,7 @@ #include #include +struct drm_panel; struct rcar_du_device; struct rcar_du_hdmienc; struct rcar_du_lvdsenc; @@ -32,6 +33,7 @@ enum rcar_du_encoder_type { struct rcar_du_encoder { struct drm_encoder base; enum rcar_du_output output; + struct rcar_du_connector *connector; struct rcar_du_hdmienc *hdmi; struct rcar_du_lvdsenc *lvds; }; @@ -44,6 +46,7 @@ struct rcar_du_encoder { struct rcar_du_connector { struct drm_connector connector; struct rcar_du_encoder *encoder; + struct drm_panel *panel; }; #define to_rcar_connector(c) \ diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c index 3bcfd161c53f..ee91481131ad 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -25,47 +26,30 @@ #include "rcar_du_kms.h" #include "rcar_du_lvdscon.h" -struct rcar_du_lvds_connector { - struct rcar_du_connector connector; - - struct { - unsigned int width_mm; /* Panel width in mm */ - unsigned int height_mm; /* Panel height in mm */ - struct videomode mode; - } panel; -}; - -#define to_rcar_lvds_connector(c) \ - container_of(c, struct rcar_du_lvds_connector, connector.connector) - static int rcar_du_lvds_connector_get_modes(struct drm_connector *connector) { - struct rcar_du_lvds_connector *lvdscon = - to_rcar_lvds_connector(connector); - struct drm_display_mode *mode; - - mode = drm_mode_create(connector->dev); - if (mode == NULL) - return 0; + struct rcar_du_connector *rcon = to_rcar_connector(connector); - mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER; - - drm_display_mode_from_videomode(&lvdscon->panel.mode, mode); - -
[PATCH v3 3/9] drm: rcar-du: Replace manual bridge implementation with DRM bridge
The rcar-du driver contains a manual implementation of HDMI and VGA bridges. Use DRM bridges to replace it. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/rcar-du/Kconfig | 6 -- drivers/gpu/drm/rcar-du/Makefile | 5 +- drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 104 +-- drivers/gpu/drm/rcar-du/rcar_du_encoder.h | 2 - drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c | 134 -- drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h | 35 drivers/gpu/drm/rcar-du/rcar_du_vgacon.c | 82 -- drivers/gpu/drm/rcar-du/rcar_du_vgacon.h | 23 - 8 files changed, 60 insertions(+), 331 deletions(-) delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_hdmienc.h delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vgacon.c delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_vgacon.h diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig index 2bab449add76..06121eeba9e5 100644 --- a/drivers/gpu/drm/rcar-du/Kconfig +++ b/drivers/gpu/drm/rcar-du/Kconfig @@ -11,12 +11,6 @@ config DRM_RCAR_DU Choose this option if you have an R-Car chipset. If M is selected the module will be called rcar-du-drm. -config DRM_RCAR_HDMI - bool "R-Car DU HDMI Encoder Support" - depends on DRM_RCAR_DU - help - Enable support for external HDMI encoders. - config DRM_RCAR_LVDS bool "R-Car DU LVDS Encoder Support" depends on DRM_RCAR_DU diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile index d3b44651061a..a492e6858691 100644 --- a/drivers/gpu/drm/rcar-du/Makefile +++ b/drivers/gpu/drm/rcar-du/Makefile @@ -4,10 +4,7 @@ rcar-du-drm-y := rcar_du_crtc.o \ rcar_du_group.o \ rcar_du_kms.o \ rcar_du_lvdscon.o \ -rcar_du_plane.o \ -rcar_du_vgacon.o - -rcar-du-drm-$(CONFIG_DRM_RCAR_HDMI)+= rcar_du_hdmienc.o +rcar_du_plane.o rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS)+= rcar_du_lvdsenc.o diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c index 3a3c9374794e..92a0405c2fb2 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c @@ -20,11 +20,9 @@ #include "rcar_du_drv.h" #include "rcar_du_encoder.h" -#include "rcar_du_hdmienc.h" #include "rcar_du_kms.h" #include "rcar_du_lvdscon.h" #include "rcar_du_lvdsenc.h" -#include "rcar_du_vgacon.h" /* - * Encoder @@ -63,29 +61,35 @@ static int rcar_du_encoder_atomic_check(struct drm_encoder *encoder, struct rcar_du_encoder *renc = to_rcar_encoder(encoder); struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode; const struct drm_display_mode *mode = &crtc_state->mode; - const struct drm_display_mode *panel_mode; struct drm_connector *connector = conn_state->connector; struct drm_device *dev = encoder->dev; - /* DAC encoders have currently no restriction on the mode. */ - if (encoder->encoder_type == DRM_MODE_ENCODER_DAC) - return 0; + /* +* Only panel-related encoder types require validation here, everything +* else is handled by the bridge drivers. +*/ + if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) { + const struct drm_display_mode *panel_mode; - if (list_empty(&connector->modes)) { - dev_dbg(dev->dev, "encoder: empty modes list\n"); - return -EINVAL; - } + if (list_empty(&connector->modes)) { + dev_dbg(dev->dev, "encoder: empty modes list\n"); + return -EINVAL; + } - panel_mode = list_first_entry(&connector->modes, - struct drm_display_mode, head); + panel_mode = list_first_entry(&connector->modes, + struct drm_display_mode, head); - /* We're not allowed to modify the resolution. */ - if (mode->hdisplay != panel_mode->hdisplay || - mode->vdisplay != panel_mode->vdisplay) - return -EINVAL; + /* We're not allowed to modify the resolution. */ + if (mode->hdisplay != panel_mode->hdisplay || + mode->vdisplay != panel_mode->vdisplay) + return -EINVAL; - /* The flat panel mode is fixed, just copy it to the adjusted mode. */ - drm_mode_copy(adjusted_mode, panel_mode); + /* +* The flat panel mode is fixed, just copy it to the adjusted +* mode. +*/ + drm_mode_copy(adjusted_mode, panel_mode); + } if (renc->lvds)
[PATCH v5.1 04/10] drm: bridge: dw-hdmi: Fix the PHY power down sequence
The PHY requires us to wait for the PHY to switch to low power mode after deasserting TXPWRON and before asserting PDDQ in the power down sequence, otherwise power down will fail. The PHY power down can be monitored though the TX_READY bit, available through I2C in the PHY registers, or the TX_PHY_LOCK bit, available through the HDMI TX registers. As the two are equivalent, let's pick the easier solution of polling the TX_PHY_LOCK bit. The power down code is currently duplicated in multiple places. To avoid spreading multiple calls to a TX_PHY_LOCK poll function, we have to refactor the power down code and group it all in a single function. Tests showed that one poll iteration was enough for TX_PHY_LOCK to become low, without requiring any additional delay. Retrying the read five times with a 1ms to 2ms delay between each attempt should thus be more than enough. Signed-off-by: Laurent Pinchart Tested-by: Neil Armstrong Reviewed-by: Jose Abreu --- drivers/gpu/drm/bridge/dw-hdmi.c | 52 +--- 1 file changed, 43 insertions(+), 9 deletions(-) Changes since v5: - Fix compilation breakage due to reordering of the patches compared to v4 diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c index d863b3393aee..3a1cd4c7ac64 100644 --- a/drivers/gpu/drm/bridge/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/dw-hdmi.c @@ -116,6 +116,7 @@ struct dw_hdmi_i2c { struct dw_hdmi_phy_data { enum dw_hdmi_phy_type type; const char *name; + unsigned int gen; bool has_svsret; }; @@ -914,6 +915,40 @@ static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable) HDMI_PHY_CONF0_SELDIPIF_MASK); } +static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi) +{ + const struct dw_hdmi_phy_data *phy = hdmi->phy; + unsigned int i; + u16 val; + + if (phy->gen == 1) { + dw_hdmi_phy_enable_tmds(hdmi, 0); + dw_hdmi_phy_enable_powerdown(hdmi, true); + return; + } + + dw_hdmi_phy_gen2_txpwron(hdmi, 0); + + /* +* Wait for TX_PHY_LOCK to be deasserted to indicate that the PHY went +* to low power mode. +*/ + for (i = 0; i < 5; ++i) { + val = hdmi_readb(hdmi, HDMI_PHY_STAT0); + if (!(val & HDMI_PHY_TX_PHY_LOCK)) + break; + + usleep_range(1000, 2000); + } + + if (val & HDMI_PHY_TX_PHY_LOCK) + dev_warn(hdmi->dev, "PHY failed to power down\n"); + else + dev_dbg(hdmi->dev, "PHY powered down in %u iterations\n", i); + + dw_hdmi_phy_gen2_pddq(hdmi, 1); +} + static int hdmi_phy_configure(struct dw_hdmi *hdmi) { u8 val, msec; @@ -946,11 +981,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi) return -EINVAL; } - /* gen2 tx power off */ - dw_hdmi_phy_gen2_txpwron(hdmi, 0); - - /* gen2 pddq */ - dw_hdmi_phy_gen2_pddq(hdmi, 1); + dw_hdmi_phy_power_off(hdmi); /* Leave low power consumption mode by asserting SVSRET. */ if (hdmi->phy->has_svsret) @@ -1025,8 +1056,6 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi) for (i = 0; i < 2; i++) { dw_hdmi_phy_sel_data_en_pol(hdmi, 1); dw_hdmi_phy_sel_interface_control(hdmi, 0); - dw_hdmi_phy_enable_tmds(hdmi, 0); - dw_hdmi_phy_enable_powerdown(hdmi, true); ret = hdmi_phy_configure(hdmi); if (ret) @@ -1256,8 +1285,7 @@ static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi) if (!hdmi->phy_enabled) return; - dw_hdmi_phy_enable_tmds(hdmi, 0); - dw_hdmi_phy_enable_powerdown(hdmi, true); + dw_hdmi_phy_power_off(hdmi); hdmi->phy_enabled = false; } @@ -1827,23 +1855,29 @@ static const struct dw_hdmi_phy_data dw_hdmi_phys[] = { { .type = DW_HDMI_PHY_DWC_HDMI_TX_PHY, .name = "DWC HDMI TX PHY", + .gen = 1, }, { .type = DW_HDMI_PHY_DWC_MHL_PHY_HEAC, .name = "DWC MHL PHY + HEAC PHY", + .gen = 2, .has_svsret = true, }, { .type = DW_HDMI_PHY_DWC_MHL_PHY, .name = "DWC MHL PHY", + .gen = 2, .has_svsret = true, }, { .type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY_HEAC, .name = "DWC HDMI 3D TX PHY + HEAC PHY", + .gen = 2, }, { .type = DW_HDMI_PHY_DWC_HDMI_3D_TX_PHY, .name = "DWC HDMI 3D TX PHY", + .gen = 2, }, { .type = DW_HDMI_PHY_DWC_HDMI20_TX_PHY, .name = "DWC HDMI 2.0 TX PHY", + .gen = 2, .has_svsret = true, } }; -- Regards, Laurent Pinchart
[PATCH v5.1 06/10] drm: bridge: dw-hdmi: Create PHY operations
The HDMI TX controller support different PHYs whose programming interface can vary significantly, especially with vendor PHYs that are not provided by Synopsys. To support them, create a PHY operation structure that can be provided by the platform glue layer. The existing PHY handling code (limited to Synopsys PHY support) is refactored into a set of default PHY operations that are used automatically when the platform glue doesn't provide its own operations. Signed-off-by: Laurent Pinchart Tested-by: Neil Armstrong Reviewed-by: Jose Abreu --- drivers/gpu/drm/bridge/dw-hdmi.c | 95 include/drm/bridge/dw_hdmi.h | 18 +++- 2 files changed, 82 insertions(+), 31 deletions(-) Changes since v5: - Undo changes from v5.1 04/10 and 05/10 diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c index c25eac8ba47b..cb2703862be2 100644 --- a/drivers/gpu/drm/bridge/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/dw-hdmi.c @@ -141,8 +141,12 @@ struct dw_hdmi { u8 edid[HDMI_EDID_LEN]; bool cable_plugin; - const struct dw_hdmi_phy_data *phy; - bool phy_enabled; + struct { + const struct dw_hdmi_phy_ops *ops; + const char *name; + void *data; + bool enabled; + } phy; struct drm_display_mode previous_mode; @@ -831,6 +835,10 @@ static void hdmi_video_packetize(struct dw_hdmi *hdmi) HDMI_VP_CONF); } +/* - + * Synopsys PHY Handling + */ + static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi, unsigned char bit) { @@ -917,7 +925,7 @@ static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable) static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi) { - const struct dw_hdmi_phy_data *phy = hdmi->phy; + const struct dw_hdmi_phy_data *phy = hdmi->phy.data; unsigned int i; u16 val; @@ -951,7 +959,7 @@ static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi) static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi) { - const struct dw_hdmi_phy_data *phy = hdmi->phy; + const struct dw_hdmi_phy_data *phy = hdmi->phy.data; unsigned int i; u8 val; @@ -987,6 +995,7 @@ static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi) static int hdmi_phy_configure(struct dw_hdmi *hdmi) { + const struct dw_hdmi_phy_data *phy = hdmi->phy.data; const struct dw_hdmi_plat_data *pdata = hdmi->plat_data; const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg; const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr; @@ -1019,7 +1028,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi) dw_hdmi_phy_power_off(hdmi); /* Leave low power consumption mode by asserting SVSRET. */ - if (hdmi->phy->has_svsret) + if (phy->has_svsret) dw_hdmi_phy_enable_svsret(hdmi, 1); /* PHY reset. The reset signal is active high on Gen2 PHYs. */ @@ -1057,7 +1066,8 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi) return dw_hdmi_phy_power_on(hdmi); } -static int dw_hdmi_phy_init(struct dw_hdmi *hdmi) +static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data, + struct drm_display_mode *mode) { int i, ret; @@ -1071,10 +1081,31 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi) return ret; } - hdmi->phy_enabled = true; return 0; } +static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi, void *data) +{ + dw_hdmi_phy_power_off(hdmi); +} + +static enum drm_connector_status dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi, + void *data) +{ + return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ? + connector_status_connected : connector_status_disconnected; +} + +static const struct dw_hdmi_phy_ops dw_hdmi_synopsys_phy_ops = { + .init = dw_hdmi_phy_init, + .disable = dw_hdmi_phy_disable, + .read_hpd = dw_hdmi_phy_read_hpd, +}; + +/* - + * HDMI TX Setup + */ + static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi) { u8 de; @@ -1289,16 +1320,6 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi, hdmi_writeb(hdmi, vsync_len, HDMI_FC_VSYNCINWIDTH); } -static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi) -{ - if (!hdmi->phy_enabled) - return; - - dw_hdmi_phy_power_off(hdmi); - - hdmi->phy_enabled = false; -} - /* HDMI Initialization Step B.4 */ static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi) { @@ -1431,9 +1452,10 @@ static int dw_hdmi_setup(struct dw_hdmi *hdmi, struct drm_display_mode *mode) hdmi_av_composer(hdmi, mode); /* HDMI Initial
[PATCH v5.1 05/10] drm: bridge: dw-hdmi: Fix the PHY power up sequence
When powering the PHY up we need to wait for the PLL to lock. This is done by polling the TX_PHY_LOCK bit in the HDMI_PHY_STAT0 register (interrupt-based wait could be implemented as well but is likely overkill). The bit is asserted when the PLL locks, but the current code incorrectly waits for the bit to be deasserted. Fix it, and while at it, replace the udelay() with a sleep as the code never runs in non-sleepable context. To be consistent with the power down implementation move the poll loop to the power off function. Signed-off-by: Laurent Pinchart Tested-by: Neil Armstrong Reviewed-by: Jose Abreu --- drivers/gpu/drm/bridge/dw-hdmi.c | 65 +++- 1 file changed, 37 insertions(+), 28 deletions(-) Changes since v5: - Fix compilation breakage due to reordering of the patches compared to v4 diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c index 3a1cd4c7ac64..c25eac8ba47b 100644 --- a/drivers/gpu/drm/bridge/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/dw-hdmi.c @@ -949,9 +949,44 @@ static void dw_hdmi_phy_power_off(struct dw_hdmi *hdmi) dw_hdmi_phy_gen2_pddq(hdmi, 1); } +static int dw_hdmi_phy_power_on(struct dw_hdmi *hdmi) +{ + const struct dw_hdmi_phy_data *phy = hdmi->phy; + unsigned int i; + u8 val; + + if (phy->gen == 1) { + dw_hdmi_phy_enable_powerdown(hdmi, false); + + /* Toggle TMDS enable. */ + dw_hdmi_phy_enable_tmds(hdmi, 0); + dw_hdmi_phy_enable_tmds(hdmi, 1); + return 0; + } + + dw_hdmi_phy_gen2_txpwron(hdmi, 1); + dw_hdmi_phy_gen2_pddq(hdmi, 0); + + /* Wait for PHY PLL lock */ + for (i = 0; i < 5; ++i) { + val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK; + if (val) + break; + + usleep_range(1000, 2000); + } + + if (!val) { + dev_err(hdmi->dev, "PHY PLL failed to lock\n"); + return -ETIMEDOUT; + } + + dev_dbg(hdmi->dev, "PHY PLL locked %u iterations\n", i); + return 0; +} + static int hdmi_phy_configure(struct dw_hdmi *hdmi) { - u8 val, msec; const struct dw_hdmi_plat_data *pdata = hdmi->plat_data; const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg; const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr; @@ -1019,33 +1054,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi) hdmi_phy_i2c_write(hdmi, HDMI_3D_TX_PHY_CKCALCTRL_OVERRIDE, HDMI_3D_TX_PHY_CKCALCTRL); - dw_hdmi_phy_enable_powerdown(hdmi, false); - - /* toggle TMDS enable */ - dw_hdmi_phy_enable_tmds(hdmi, 0); - dw_hdmi_phy_enable_tmds(hdmi, 1); - - /* gen2 tx power on */ - dw_hdmi_phy_gen2_txpwron(hdmi, 1); - dw_hdmi_phy_gen2_pddq(hdmi, 0); - - /* Wait for PHY PLL lock */ - msec = 5; - do { - val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK; - if (!val) - break; - - if (msec == 0) { - dev_err(hdmi->dev, "PHY PLL not locked\n"); - return -ETIMEDOUT; - } - - udelay(1000); - msec--; - } while (1); - - return 0; + return dw_hdmi_phy_power_on(hdmi); } static int dw_hdmi_phy_init(struct dw_hdmi *hdmi) -- Regards, Laurent Pinchart
Re: [PATCHv2] arm64: dts: r8a7795: salvator-x: Set drive-strength for ravb pins
Hi Simon, On 2016-12-08 14:31:38 +0100, Simon Horman wrote: > On Mon, Dec 05, 2016 at 06:43:10PM +0100, Niklas Söderlund wrote: > > The EthernetAVB should not depend on the bootloader to setup correct > > drive-strength values. Values for drive-strength where found by > > examining the registers after the bootloader has configured the > > registers and successfully used the EthernetAVB. > > > > Signed-off-by: Niklas Söderlund > > I believe this patch has run-time dependencies on PFC patches and will > result in a regression without them. Please resubmit or otherwise ping me > once chose changes are present in an (rc) release or immutable branch. The dependency for this DT change is now present in v4.11-rc1, see 1. If it's convenient for you feel free to pick up this patch. 1. b25719eb938eb39a ("pinctrl: sh-pfc: r8a7795: Add group for AVB MDIO and MII pins") > > Thanks! -- Regards, Niklas Söderlund
Re: [PATCH v3 2/3] v4l: vsp1: Extend VSP1 module API to allow DRM callbacks
Hi Laurent, On 05/03/17 21:58, Laurent Pinchart wrote: > Hi Kieran, > > Thank you for the patch. > > On Sunday 05 Mar 2017 16:00:03 Kieran Bingham wrote: >> To be able to perform page flips in DRM without flicker we need to be >> able to notify the rcar-du module when the VSP has completed its >> processing. >> >> We must not have bidirectional dependencies on the two components to >> maintain support for loadable modules, thus we extend the API to allow >> a callback to be registered within the VSP DRM interface. >> >> Signed-off-by: Kieran Bingham >> --- >> drivers/media/platform/vsp1/vsp1_drm.c | 17 + >> drivers/media/platform/vsp1/vsp1_drm.h | 11 +++ >> include/media/vsp1.h | 13 + >> 3 files changed, 41 insertions(+) >> >> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c >> b/drivers/media/platform/vsp1/vsp1_drm.c index 4ee437c7ff0c..d93bf7d3a39e >> 100644 >> --- a/drivers/media/platform/vsp1/vsp1_drm.c >> +++ b/drivers/media/platform/vsp1/vsp1_drm.c >> @@ -37,6 +37,14 @@ void vsp1_drm_display_start(struct vsp1_device *vsp1) >> vsp1_dlm_irq_display_start(vsp1->drm->pipe.output->dlm); >> } >> >> +static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe) >> +{ >> +struct vsp1_drm *drm = to_vsp1_drm(pipe); >> + >> +if (drm->du_complete) >> +drm->du_complete(drm->du_private); >> +} >> + >> /* >> * DU Driver API >> */ >> @@ -96,6 +104,7 @@ int vsp1_du_setup_lif(struct device *dev, const struct >> vsp1_du_lif_config *cfg) } >> >> pipe->num_inputs = 0; >> +vsp1->drm->du_complete = NULL; >> >> vsp1_dlm_reset(pipe->output->dlm); >> vsp1_device_put(vsp1); >> @@ -200,6 +209,13 @@ int vsp1_du_setup_lif(struct device *dev, const struct >> vsp1_du_lif_config *cfg) if (ret < 0) >> return ret; >> >> +/* >> + * Register a callback to allow us to notify the DRM framework of > frame > > s/framework/driver/ > >> + * completion events. >> + */ >> +vsp1->drm->du_complete = cfg->callback; >> +vsp1->drm->du_private = cfg->callback_data; >> + >> ret = media_pipeline_start(&pipe->output->entity.subdev.entity, >>&pipe->pipe); >> if (ret < 0) { >> @@ -607,6 +623,7 @@ int vsp1_drm_init(struct vsp1_device *vsp1) >> pipe->lif = &vsp1->lif->entity; >> pipe->output = vsp1->wpf[0]; >> pipe->output->pipe = pipe; >> +pipe->frame_end = vsp1_du_pipeline_frame_end; >> >> return 0; >> } >> diff --git a/drivers/media/platform/vsp1/vsp1_drm.h >> b/drivers/media/platform/vsp1/vsp1_drm.h index c8d2f88fc483..3de2095cb0ce >> 100644 >> --- a/drivers/media/platform/vsp1/vsp1_drm.h >> +++ b/drivers/media/platform/vsp1/vsp1_drm.h >> @@ -23,6 +23,8 @@ >> * @num_inputs: number of active pipeline inputs at the beginning of an >> update >> * @inputs: source crop rectangle, destination compose rectangle and >> z-order >> * position for every input >> + * @du_complete: frame completion callback for the DU driver (optional) >> + * @du_private: data to be passed to the du_complete callback >> */ >> struct vsp1_drm { >> struct vsp1_pipeline pipe; >> @@ -33,8 +35,17 @@ struct vsp1_drm { >> struct v4l2_rect compose; >> unsigned int zpos; >> } inputs[VSP1_MAX_RPF]; >> + >> +/* Frame syncronisation */ > > s/syncronisation/synchronisation/ > >> +void (*du_complete)(void *); >> +void *du_private; >> }; >> >> +static inline struct vsp1_drm *to_vsp1_drm(struct vsp1_pipeline *pipe) >> +{ >> +return container_of(pipe, struct vsp1_drm, pipe); >> +} >> + >> int vsp1_drm_init(struct vsp1_device *vsp1); >> void vsp1_drm_cleanup(struct vsp1_device *vsp1); >> int vsp1_drm_create_links(struct vsp1_device *vsp1); >> diff --git a/include/media/vsp1.h b/include/media/vsp1.h >> index bfc701f04f3f..d59d0adf560d 100644 >> --- a/include/media/vsp1.h >> +++ b/include/media/vsp1.h >> @@ -20,9 +20,22 @@ struct device; >> >> int vsp1_du_init(struct device *dev); >> >> +/** >> + * struct vsp1_du_lif_config - VSP LIF configuration >> + * @width: output frame width >> + * @height: output frame height >> + * @callback: frame completion callback function (optional) >> + * @callback_data: data to be passed to the frame completion callback >> + * >> + * When the optional callback is provided to the VSP1, the VSP1 must >> guarantee >> + * that one completion callback is performed after every >> vsp1_du_atomic_flush() > > This paragraph should be part of the @callback documentation. I would phrase > it as > > * @callback: frame completion callback function (optional). When a callback > * is provided, the VSP driver guarantees that it will be called > * once and only once for each vsp1_du_atomic_flush() call. > > With this fixed, > > Reviewed-by: Laurent Pinchart >
Re: [PATCH v3 3/3] drm: rcar-du: Register a completion callback with VSP1
Hi Kieran, Thank you for the patch. On Sunday 05 Mar 2017 16:00:04 Kieran Bingham wrote: > Currently we process page flip events on every display interrupt, > however this does not take into consideration the processing time needed > by the VSP1 utilised in the pipeline. > > Register a callback with the VSP driver to obtain completion events, and > track them so that we only perform page flips when the full display > pipeline has completed for the frame. > > Signed-off-by: Kieran Bingham > --- > drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 8 ++-- > drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 1 + > drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 9 + > 3 files changed, 16 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c > b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 2aceb84fc15d..c1812e20 > 100644 > --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c > +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c > @@ -299,7 +299,7 @@ static void rcar_du_crtc_update_planes(struct > rcar_du_crtc *rcrtc) * Page Flip > */ > > -static void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc) > +void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc) > { > struct drm_pending_vblank_event *event; > struct drm_device *dev = rcrtc->crtc.dev; > @@ -571,6 +571,7 @@ static const struct drm_crtc_funcs crtc_funcs = { > static irqreturn_t rcar_du_crtc_irq(int irq, void *arg) > { > struct rcar_du_crtc *rcrtc = arg; > + struct rcar_du_device *rcdu = rcrtc->group->dev; > irqreturn_t ret = IRQ_NONE; > u32 status; > > @@ -579,7 +580,10 @@ static irqreturn_t rcar_du_crtc_irq(int irq, void *arg) > > if (status & DSSR_FRM) { > drm_crtc_handle_vblank(&rcrtc->crtc); > - rcar_du_crtc_finish_page_flip(rcrtc); > + > + if (rcdu->info->gen < 3) > + rcar_du_crtc_finish_page_flip(rcrtc); > + > ret = IRQ_HANDLED; > } > > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h > b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h index a7194812997e..ebdbff9d8e59 > 100644 > --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h > +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h > @@ -71,5 +71,6 @@ void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc); > > void rcar_du_crtc_route_output(struct drm_crtc *crtc, > enum rcar_du_output output); > +void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc); > > #endif /* __RCAR_DU_CRTC_H__ */ > diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c > b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index b0ff304ce3dc..cbb6f54c99ef > 100644 > --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c > +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c > @@ -28,6 +28,13 @@ > #include "rcar_du_kms.h" > #include "rcar_du_vsp.h" > > +static void rcar_du_vsp_complete(void *private) > +{ > + struct rcar_du_crtc *crtc = (struct rcar_du_crtc *)private; I'll remove the cast when applying, as pointed out by Sergei. Reviewed-by: Laurent Pinchart > + > + rcar_du_crtc_finish_page_flip(crtc); > +} > + > void rcar_du_vsp_enable(struct rcar_du_crtc *crtc) > { > const struct drm_display_mode *mode = &crtc->crtc.state- >adjusted_mode; > @@ -35,6 +42,8 @@ void rcar_du_vsp_enable(struct rcar_du_crtc *crtc) > struct vsp1_du_lif_config cfg = { > .width = mode->hdisplay, > .height = mode->vdisplay, > + .callback = rcar_du_vsp_complete, > + .callback_data = crtc, > }; > struct rcar_du_plane_state state = { > .state = { -- Regards, Laurent Pinchart
Re: [PATCH v3 2/3] v4l: vsp1: Extend VSP1 module API to allow DRM callbacks
Hi Kieran, Thank you for the patch. On Sunday 05 Mar 2017 16:00:03 Kieran Bingham wrote: > To be able to perform page flips in DRM without flicker we need to be > able to notify the rcar-du module when the VSP has completed its > processing. > > We must not have bidirectional dependencies on the two components to > maintain support for loadable modules, thus we extend the API to allow > a callback to be registered within the VSP DRM interface. > > Signed-off-by: Kieran Bingham > --- > drivers/media/platform/vsp1/vsp1_drm.c | 17 + > drivers/media/platform/vsp1/vsp1_drm.h | 11 +++ > include/media/vsp1.h | 13 + > 3 files changed, 41 insertions(+) > > diff --git a/drivers/media/platform/vsp1/vsp1_drm.c > b/drivers/media/platform/vsp1/vsp1_drm.c index 4ee437c7ff0c..d93bf7d3a39e > 100644 > --- a/drivers/media/platform/vsp1/vsp1_drm.c > +++ b/drivers/media/platform/vsp1/vsp1_drm.c > @@ -37,6 +37,14 @@ void vsp1_drm_display_start(struct vsp1_device *vsp1) > vsp1_dlm_irq_display_start(vsp1->drm->pipe.output->dlm); > } > > +static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe) > +{ > + struct vsp1_drm *drm = to_vsp1_drm(pipe); > + > + if (drm->du_complete) > + drm->du_complete(drm->du_private); > +} > + > /* > * DU Driver API > */ > @@ -96,6 +104,7 @@ int vsp1_du_setup_lif(struct device *dev, const struct > vsp1_du_lif_config *cfg) } > > pipe->num_inputs = 0; > + vsp1->drm->du_complete = NULL; > > vsp1_dlm_reset(pipe->output->dlm); > vsp1_device_put(vsp1); > @@ -200,6 +209,13 @@ int vsp1_du_setup_lif(struct device *dev, const struct > vsp1_du_lif_config *cfg) if (ret < 0) > return ret; > > + /* > + * Register a callback to allow us to notify the DRM framework of frame s/framework/driver/ > + * completion events. > + */ > + vsp1->drm->du_complete = cfg->callback; > + vsp1->drm->du_private = cfg->callback_data; > + > ret = media_pipeline_start(&pipe->output->entity.subdev.entity, > &pipe->pipe); > if (ret < 0) { > @@ -607,6 +623,7 @@ int vsp1_drm_init(struct vsp1_device *vsp1) > pipe->lif = &vsp1->lif->entity; > pipe->output = vsp1->wpf[0]; > pipe->output->pipe = pipe; > + pipe->frame_end = vsp1_du_pipeline_frame_end; > > return 0; > } > diff --git a/drivers/media/platform/vsp1/vsp1_drm.h > b/drivers/media/platform/vsp1/vsp1_drm.h index c8d2f88fc483..3de2095cb0ce > 100644 > --- a/drivers/media/platform/vsp1/vsp1_drm.h > +++ b/drivers/media/platform/vsp1/vsp1_drm.h > @@ -23,6 +23,8 @@ > * @num_inputs: number of active pipeline inputs at the beginning of an > update > * @inputs: source crop rectangle, destination compose rectangle and > z-order > * position for every input > + * @du_complete: frame completion callback for the DU driver (optional) > + * @du_private: data to be passed to the du_complete callback > */ > struct vsp1_drm { > struct vsp1_pipeline pipe; > @@ -33,8 +35,17 @@ struct vsp1_drm { > struct v4l2_rect compose; > unsigned int zpos; > } inputs[VSP1_MAX_RPF]; > + > + /* Frame syncronisation */ s/syncronisation/synchronisation/ > + void (*du_complete)(void *); > + void *du_private; > }; > > +static inline struct vsp1_drm *to_vsp1_drm(struct vsp1_pipeline *pipe) > +{ > + return container_of(pipe, struct vsp1_drm, pipe); > +} > + > int vsp1_drm_init(struct vsp1_device *vsp1); > void vsp1_drm_cleanup(struct vsp1_device *vsp1); > int vsp1_drm_create_links(struct vsp1_device *vsp1); > diff --git a/include/media/vsp1.h b/include/media/vsp1.h > index bfc701f04f3f..d59d0adf560d 100644 > --- a/include/media/vsp1.h > +++ b/include/media/vsp1.h > @@ -20,9 +20,22 @@ struct device; > > int vsp1_du_init(struct device *dev); > > +/** > + * struct vsp1_du_lif_config - VSP LIF configuration > + * @width: output frame width > + * @height: output frame height > + * @callback: frame completion callback function (optional) > + * @callback_data: data to be passed to the frame completion callback > + * > + * When the optional callback is provided to the VSP1, the VSP1 must > guarantee > + * that one completion callback is performed after every > vsp1_du_atomic_flush() This paragraph should be part of the @callback documentation. I would phrase it as * @callback: frame completion callback function (optional). When a callback *is provided, the VSP driver guarantees that it will be called *once and only once for each vsp1_du_atomic_flush() call. With this fixed, Reviewed-by: Laurent Pinchart If you're fine with the above changes there's no need to resubmit, I'll fix when applying the patch. > + */ > struct vsp1_du_lif_config { > unsigned int width; >
Re: [PATCH v3 1/3] v4l: vsp1: Postpone frame end handling in event of display list race
Hi Kieran, Thank you for the patch. On Sunday 05 Mar 2017 16:00:02 Kieran Bingham wrote: > If we try to commit the display list while an update is pending, we have > missed our opportunity. The display list manager will hold the commit > until the next interrupt. > > In this event, we skip the pipeline completion callback handler so that > the pipeline will not mistakenly report frame completion to the user. > > Signed-off-by: Kieran Bingham Reviewed-by: Laurent Pinchart > --- > drivers/media/platform/vsp1/vsp1_dl.c | 19 +-- > drivers/media/platform/vsp1/vsp1_dl.h | 2 +- > drivers/media/platform/vsp1/vsp1_pipe.c | 13 - > 3 files changed, 30 insertions(+), 4 deletions(-) > > diff --git a/drivers/media/platform/vsp1/vsp1_dl.c > b/drivers/media/platform/vsp1/vsp1_dl.c index b9e5027778ff..f449ca689554 > 100644 > --- a/drivers/media/platform/vsp1/vsp1_dl.c > +++ b/drivers/media/platform/vsp1/vsp1_dl.c > @@ -562,9 +562,19 @@ void vsp1_dlm_irq_display_start(struct vsp1_dl_manager > *dlm) spin_unlock(&dlm->lock); > } > > -void vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm) > +/** > + * vsp1_dlm_irq_frame_end - Display list handler for the frame end > interrupt + * @dlm: the display list manager > + * > + * Return true if the previous display list has completed at frame end, or > false + * if it has been delayed by one frame because the display list > commit raced + * with the frame end interrupt. The function always returns > true in header mode + * as display list processing is then not continuous > and races never occur. + */ > +bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm) > { > struct vsp1_device *vsp1 = dlm->vsp1; > + bool completed = false; > > spin_lock(&dlm->lock); > > @@ -576,8 +586,10 @@ void vsp1_dlm_irq_frame_end(struct vsp1_dl_manager > *dlm) * perform any operation as there can't be any new display list queued > * in that case. >*/ > - if (dlm->mode == VSP1_DL_MODE_HEADER) > + if (dlm->mode == VSP1_DL_MODE_HEADER) { > + completed = true; > goto done; > + } > > /* >* The UPD bit set indicates that the commit operation raced with the > @@ -597,6 +609,7 @@ void vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm) > if (dlm->queued) { > dlm->active = dlm->queued; > dlm->queued = NULL; > + completed = true; > } > > /* > @@ -619,6 +632,8 @@ void vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm) > > done: > spin_unlock(&dlm->lock); > + > + return completed; > } > > /* Hardware Setup */ > diff --git a/drivers/media/platform/vsp1/vsp1_dl.h > b/drivers/media/platform/vsp1/vsp1_dl.h index 7131aa3c5978..6ec1380a10af > 100644 > --- a/drivers/media/platform/vsp1/vsp1_dl.h > +++ b/drivers/media/platform/vsp1/vsp1_dl.h > @@ -28,7 +28,7 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device > *vsp1, void vsp1_dlm_destroy(struct vsp1_dl_manager *dlm); > void vsp1_dlm_reset(struct vsp1_dl_manager *dlm); > void vsp1_dlm_irq_display_start(struct vsp1_dl_manager *dlm); > -void vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm); > +bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm); > > struct vsp1_dl_list *vsp1_dl_list_get(struct vsp1_dl_manager *dlm); > void vsp1_dl_list_put(struct vsp1_dl_list *dl); > diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c > b/drivers/media/platform/vsp1/vsp1_pipe.c index 35364f594e19..d15327701ad8 > 100644 > --- a/drivers/media/platform/vsp1/vsp1_pipe.c > +++ b/drivers/media/platform/vsp1/vsp1_pipe.c > @@ -304,10 +304,21 @@ bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe) > > void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe) > { > + bool completed; > + > if (pipe == NULL) > return; > > - vsp1_dlm_irq_frame_end(pipe->output->dlm); > + completed = vsp1_dlm_irq_frame_end(pipe->output->dlm); > + if (!completed) { > + /* > + * If the DL commit raced with the frame end interrupt, the > + * commit ends up being postponed by one frame. Return > + * immediately without calling the pipeline's frame end handler > + * or incrementing the sequence number. > + */ > + return; > + } > > if (pipe->frame_end) > pipe->frame_end(pipe); -- Regards, Laurent Pinchart
[PATCH 2/2] Formatting updates to resolve checkpatch errors in ks_wlan_ioctl.h.
Updating macros to be wrapped in parentheses to accomodate checkpatch errors throughout the header. This change, combined with the previous patch, resolves all outstanding warnings/errors produce by checkpatch. Signed-off-by: Matthew Giassa --- drivers/staging/ks7010/ks_wlan_ioctl.h | 66 +- 1 file changed, 32 insertions(+), 34 deletions(-) diff --git a/drivers/staging/ks7010/ks_wlan_ioctl.h b/drivers/staging/ks7010/ks_wlan_ioctl.h index 0e92495..bfb8555 100644 --- a/drivers/staging/ks7010/ks_wlan_ioctl.h +++ b/drivers/staging/ks7010/ks_wlan_ioctl.h @@ -15,43 +15,41 @@ #include /* The low order bit identify a SET (0) or a GET (1) ioctl. */ -/* SIOCIWFIRSTPRIV + 0 */ -/* former KS_WLAN_GET_DRIVER_VERSION SIOCIWFIRSTPRIV + 1 */ -/* SIOCIWFIRSTPRIV + 2 */ -#define KS_WLAN_GET_FIRM_VERSION SIOCIWFIRSTPRIV + 3 +/* (SIOCIWFIRSTPRIV + 0) */ +/* former KS_WLAN_GET_DRIVER_VERSION (SIOCIWFIRSTPRIV + 1) */ +/* (SIOCIWFIRSTPRIV + 2) */ +#define KS_WLAN_GET_FIRM_VERSION (SIOCIWFIRSTPRIV + 3) #ifdef WPS -#define KS_WLAN_SET_WPS_ENABLE SIOCIWFIRSTPRIV + 4 -#define KS_WLAN_GET_WPS_ENABLE SIOCIWFIRSTPRIV + 5 -#define KS_WLAN_SET_WPS_PROBE_REQ SIOCIWFIRSTPRIV + 6 +#define KS_WLAN_SET_WPS_ENABLE (SIOCIWFIRSTPRIV + 4) +#define KS_WLAN_GET_WPS_ENABLE (SIOCIWFIRSTPRIV + 5) +#define KS_WLAN_SET_WPS_PROBE_REQ (SIOCIWFIRSTPRIV + 6) #endif -#define KS_WLAN_GET_EEPROM_CKSUM SIOCIWFIRSTPRIV + 7 -#define KS_WLAN_SET_PREAMBLE SIOCIWFIRSTPRIV + 8 -#define KS_WLAN_GET_PREAMBLE SIOCIWFIRSTPRIV + 9 -#define KS_WLAN_SET_POWER_SAVE SIOCIWFIRSTPRIV + 10 -#define KS_WLAN_GET_POWER_SAVE SIOCIWFIRSTPRIV + 11 -#define KS_WLAN_SET_SCAN_TYPE SIOCIWFIRSTPRIV + 12 -#define KS_WLAN_GET_SCAN_TYPE SIOCIWFIRSTPRIV + 13 -#define KS_WLAN_SET_RX_GAINSIOCIWFIRSTPRIV + 14 -#define KS_WLAN_GET_RX_GAINSIOCIWFIRSTPRIV + 15 -#define KS_WLAN_HOSTT SIOCIWFIRSTPRIV + 16 /* unused */ -/* #define KS_WLAN_SET_REGION SIOCIWFIRSTPRIV + 17 */ -#define KS_WLAN_SET_BEACON_LOSTSIOCIWFIRSTPRIV + 18 -#define KS_WLAN_GET_BEACON_LOSTSIOCIWFIRSTPRIV + 19 - -#define KS_WLAN_SET_TX_GAINSIOCIWFIRSTPRIV + 20 -#define KS_WLAN_GET_TX_GAINSIOCIWFIRSTPRIV + 21 - +#define KS_WLAN_GET_EEPROM_CKSUM (SIOCIWFIRSTPRIV + 7) +#define KS_WLAN_SET_PREAMBLE (SIOCIWFIRSTPRIV + 8) +#define KS_WLAN_GET_PREAMBLE (SIOCIWFIRSTPRIV + 9) +#define KS_WLAN_SET_POWER_SAVE (SIOCIWFIRSTPRIV + 10) +#define KS_WLAN_GET_POWER_SAVE (SIOCIWFIRSTPRIV + 11) +#define KS_WLAN_SET_SCAN_TYPE (SIOCIWFIRSTPRIV + 12) +#define KS_WLAN_GET_SCAN_TYPE (SIOCIWFIRSTPRIV + 13) +#define KS_WLAN_SET_RX_GAIN(SIOCIWFIRSTPRIV + 14) +#define KS_WLAN_GET_RX_GAIN(SIOCIWFIRSTPRIV + 15) +#define KS_WLAN_HOSTT (SIOCIWFIRSTPRIV + 16) /* unused */ +/* #define KS_WLAN_SET_REGION (SIOCIWFIRSTPRIV + 17) */ +#define KS_WLAN_SET_BEACON_LOST(SIOCIWFIRSTPRIV + 18) +#define KS_WLAN_GET_BEACON_LOST(SIOCIWFIRSTPRIV + 19) +#define KS_WLAN_SET_TX_GAIN(SIOCIWFIRSTPRIV + 20) +#define KS_WLAN_GET_TX_GAIN(SIOCIWFIRSTPRIV + 21) /* for KS7010 */ -#define KS_WLAN_SET_PHY_TYPE SIOCIWFIRSTPRIV + 22 -#define KS_WLAN_GET_PHY_TYPE SIOCIWFIRSTPRIV + 23 -#define KS_WLAN_SET_CTS_MODE SIOCIWFIRSTPRIV + 24 -#define KS_WLAN_GET_CTS_MODE SIOCIWFIRSTPRIV + 25 -/* SIOCIWFIRSTPRIV + 26 */ -/* SIOCIWFIRSTPRIV + 27 */ -#define KS_WLAN_SET_SLEEP_MODE SIOCIWFIRSTPRIV + 28 /* sleep mode */ -#define KS_WLAN_GET_SLEEP_MODE SIOCIWFIRSTPRIV + 29 /* sleep mode */ -/* SIOCIWFIRSTPRIV + 30 */ -/* SIOCIWFIRSTPRIV + 31 */ +#define KS_WLAN_SET_PHY_TYPE (SIOCIWFIRSTPRIV + 22) +#define KS_WLAN_GET_PHY_TYPE (SIOCIWFIRSTPRIV + 23) +#define KS_WLAN_SET_CTS_MODE (SIOCIWFIRSTPRIV + 24) +#define KS_WLAN_GET_CTS_MODE (SIOCIWFIRSTPRIV + 25) +/* (SIOCIWFIRSTPRIV + 26) */ +/* (SIOCIWFIRSTPRIV + 27) */ +#define KS_WLAN_SET_SLEEP_MODE (SIOCIWFIRSTPRIV + 28) /* sleep mode */ +#define KS_WLAN_GET_SLEEP_MODE (SIOCIWFIRSTPRIV + 29) /* sleep mode */ +/* (SIOCIWFIRSTPRIV + 30) */ +/* (SIOCIWFIRSTPRIV + 31) */ #ifdef __KERNEL__ -- 2.7.4
[PATCH 1/2] Formatting updates to remove checkpatch warnings in ks_wlan_ioctl.h.
Implementing some minor formatting changes to remove checkpatch warnings. Removing space-hardtab instances. Removing C++-style line comments in favor of C-style equivalent. Re-aligning function prototype arguments to remove related checkpatch warning. Signed-off-by: Matthew Giassa --- drivers/staging/ks7010/ks_wlan_ioctl.h | 16 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/staging/ks7010/ks_wlan_ioctl.h b/drivers/staging/ks7010/ks_wlan_ioctl.h index 8e62b10..0e92495 100644 --- a/drivers/staging/ks7010/ks_wlan_ioctl.h +++ b/drivers/staging/ks7010/ks_wlan_ioctl.h @@ -1,6 +1,6 @@ /* * Driver for KeyStream 11b/g wireless LAN - * + * * Copyright (c) 2005-2008 KeyStream Corp. * Copyright (C) 2009 Renesas Technology Corp. * @@ -20,8 +20,8 @@ /* SIOCIWFIRSTPRIV + 2 */ #define KS_WLAN_GET_FIRM_VERSION SIOCIWFIRSTPRIV + 3 #ifdef WPS -#define KS_WLAN_SET_WPS_ENABLE SIOCIWFIRSTPRIV + 4 -#define KS_WLAN_GET_WPS_ENABLE SIOCIWFIRSTPRIV + 5 +#define KS_WLAN_SET_WPS_ENABLE SIOCIWFIRSTPRIV + 4 +#define KS_WLAN_GET_WPS_ENABLE SIOCIWFIRSTPRIV + 5 #define KS_WLAN_SET_WPS_PROBE_REQ SIOCIWFIRSTPRIV + 6 #endif #define KS_WLAN_GET_EEPROM_CKSUM SIOCIWFIRSTPRIV + 7 @@ -33,8 +33,8 @@ #define KS_WLAN_GET_SCAN_TYPE SIOCIWFIRSTPRIV + 13 #define KS_WLAN_SET_RX_GAINSIOCIWFIRSTPRIV + 14 #define KS_WLAN_GET_RX_GAINSIOCIWFIRSTPRIV + 15 -#define KS_WLAN_HOSTT SIOCIWFIRSTPRIV + 16/* unused */ -//#define KS_WLAN_SET_REGIONSIOCIWFIRSTPRIV + 17 +#define KS_WLAN_HOSTT SIOCIWFIRSTPRIV + 16 /* unused */ +/* #define KS_WLAN_SET_REGION SIOCIWFIRSTPRIV + 17 */ #define KS_WLAN_SET_BEACON_LOSTSIOCIWFIRSTPRIV + 18 #define KS_WLAN_GET_BEACON_LOSTSIOCIWFIRSTPRIV + 19 @@ -48,8 +48,8 @@ #define KS_WLAN_GET_CTS_MODE SIOCIWFIRSTPRIV + 25 /* SIOCIWFIRSTPRIV + 26 */ /* SIOCIWFIRSTPRIV + 27 */ -#define KS_WLAN_SET_SLEEP_MODE SIOCIWFIRSTPRIV + 28/* sleep mode */ -#define KS_WLAN_GET_SLEEP_MODE SIOCIWFIRSTPRIV + 29/* sleep mode */ +#define KS_WLAN_SET_SLEEP_MODE SIOCIWFIRSTPRIV + 28 /* sleep mode */ +#define KS_WLAN_GET_SLEEP_MODE SIOCIWFIRSTPRIV + 29 /* sleep mode */ /* SIOCIWFIRSTPRIV + 30 */ /* SIOCIWFIRSTPRIV + 31 */ @@ -60,7 +60,7 @@ int ks_wlan_read_config_file(struct ks_wlan_private *priv); int ks_wlan_setup_parameter(struct ks_wlan_private *priv, -unsigned int commit_flag); + unsigned int commit_flag); #endif /* __KERNEL__ */ -- 2.7.4
[PATCH v2.2] v4l: Clearly document interactions between formats, controls and buffers
V4L2 exposes parameters that influence buffers sizes through the format ioctls (VIDIOC_G_FMT, VIDIOC_TRY_FMT, VIDIOC_S_FMT, and possibly VIDIOC_G_SELECTION and VIDIOC_S_SELECTION). Other parameters not part of the format structure may also influence buffer sizes or buffer layout in general. One existing such parameter is rotation, which is implemented by the V4L2_CID_ROTATE control and thus exposed through the V4L2 control ioctls. The interaction between those parameters and buffers is currently only partially specified by the V4L2 API. In particular interactions between controls and buffers isn't specified at all. The behaviour of the VIDIOC_S_FMT and VIDIOC_S_SELECTION ioctls when buffers are allocated is also not fully specified. This patch clearly defines and documents the interactions between formats, selections, controls and buffers. The preparatory discussions for the documentation change considered completely disallowing controls that change the buffer size or layout, in favour of extending the format API with a new ioctl that would bundle those controls with format information. The idea has been rejected, as this would essentially be a restricted version of the upcoming request API that wouldn't bring any additional value. Another option we have considered was to mandate the use of the request API to modify controls that influence buffer size or layout. This has also been rejected on the grounds that requiring the request API to change rotation even when streaming is stopped would significantly complicate implementation of drivers and usage of the V4L2 API for applications. Applications will however be required to use the upcoming request API to change at runtime formats or controls that influence the buffer size or layout, because of the need to synchronize buffers with the formats and controls. Otherwise there would be no way to interpret the content of a buffer correctly. Signed-off-by: Laurent Pinchart Acked-by: Sakari Ailus --- Changes since v2.1: - Fixed small issues in commit message - Simplified wording of one sentence in the documentation Changes since v2: - Document the interaction with ioctls that can affect formats (VIDIOC_S_SELECTION, VIDIOC_S_INPUT, VIDIOC_S_OUTPUT, VIDIOC_S_STD and VIDIOC_S_DV_TIMINGS) - Clarify the format/control change order --- Documentation/media/uapi/v4l/buffer.rst | 108 1 file changed, 108 insertions(+) diff --git a/Documentation/media/uapi/v4l/buffer.rst b/Documentation/media/uapi/v4l/buffer.rst index ac58966ccb9b..60d62a5824f8 100644 --- a/Documentation/media/uapi/v4l/buffer.rst +++ b/Documentation/media/uapi/v4l/buffer.rst @@ -34,6 +34,114 @@ flags are copied from the OUTPUT video buffer to the CAPTURE video buffer. +Interactions between formats, controls and buffers +== + +V4L2 exposes parameters that influence the buffer size, or the way data is +laid out in the buffer. Those parameters are exposed through both formats and +controls. One example of such a control is the ``V4L2_CID_ROTATE`` control +that modifies the direction in which pixels are stored in the buffer, as well +as the buffer size when the selected format includes padding at the end of +lines. + +The set of information needed to interpret the content of a buffer (e.g. the +pixel format, the line stride, the tiling orientation or the rotation) is +collectively referred to in the rest of this section as the buffer layout. + +Modifying formats or controls that influence the buffer size or layout require +the stream to be stopped. Any attempt at such a modification while the stream +is active shall cause the ioctl setting the format or the control to return +the ``EBUSY`` error code. + +Controls that only influence the buffer layout can be modified at any time +when the stream is stopped. As they don't influence the buffer size, no +special handling is needed to synchronize those controls with buffer +allocation. + +Formats and controls that influence the buffer size interact with buffer +allocation. As buffer allocation is an expensive operation, drivers should +allow format or controls that influence the buffer size to be changed with +buffers allocated. A typical ioctl sequence to modify format and controls is + + #. VIDIOC_STREAMOFF + #. VIDIOC_S_EXT_CTRLS + #. VIDIOC_S_FMT + #. VIDIOC_QBUF + #. VIDIOC_STREAMON + +.. note:: + + The API doesn't mandate the above order for control (2.) and format (3.) + changes. Format and controls can be set in a different order, or even + interleaved, depending on the device and use case. For instance some + controls might behave differently for different pixel formats, in which + case the format might need to be set first. + +Queued buffers must be large enough for the new format or controls. + +Drivers shall return a ``ENOSPC`` error in response to format change +(:c:func:`VIDIOC_S_FMT`) or control changes (:c:func:`VIDIOC_S_CTRL` or +:c:func
Re: [PATCH v2.1] v4l: Clearly document interactions between formats, controls and buffers
Hi Laurent, Thanks for the update. On Sun, Mar 05, 2017 at 04:39:36PM +0200, Laurent Pinchart wrote: > V4L2 exposes parameters that influence buffers sizes through the format > ioctls (VIDIOC_G_FMT, VIDIOC_TRY_FMT, VIDIOC_S_FMT, and possibly > VIDIOC_G_SELECTION and VIDIOC_S_SELECTION). Other parameters not part of > the format structure may also influence buffer sizes or buffer layout in > general. One existing such parameter is rotation, which is implemented > by the VIDIOC_ROTATE control and thus exposed through the V4L2 control V4L2_CID_ROTATE > ioctls. > > The interaction between those parameters and buffers is currently only > partially specified by the V4L2 API. In particular interactions between > controls and buffers isn't specified at all. The behaviour of the > VIDIOC_S_FMT and VIDIOC_S_SELECTION ioctls when buffers are allocated is > also not fully specified. > > This commit clearly defines and documents the interactions between It's say it's a patch, and most kernel developers seem to agree: $ git log v4.9..v4.10|grep -ci 'this patch' 1816 $ git log v4.9..v4.10|grep -ci 'this commit' 217 Up to you. :-) > formats, selections, controls and buffers. > > The preparatory discussions for the documentation change considered > completely disallowing controls that change the buffer size or layout, > in favour of extending the format API with a new ioctl that would bundle > those controls with format information. The idea has been rejected, as > this would essentially be a restricted version of the upcoming request > API that wouldn't bring any additional value. > > Another option we have considered was to mandate the use of the request > API to modify controls that influence buffer size or layout. This has > also been rejected on the grounds that requiring the request API to > change rotation even when streaming is stopped would significantly > complicate implementation of drivers and usage of the V4L2 API for > applications. > > Applications will however be required to use the upcoming request API to > change at runtime formats or controls that influence the buffer size or > layout, because of the need to synchronize buffers with the formats and > controls. Otherwise there would be no way to interpret the content of a > buffer correctly. > > Signed-off-by: Laurent Pinchart > --- > Changes since v2: > > - Document the interaction with ioctls that can affect formats > (VIDIOC_S_SELECTION, VIDIOC_S_INPUT, VIDIOC_S_OUTPUT, VIDIOC_S_STD and > VIDIOC_S_DV_TIMINGS) > - Clarify the format/control change order > --- > Documentation/media/uapi/v4l/buffer.rst | 108 > > 1 file changed, 108 insertions(+) > > diff --git a/Documentation/media/uapi/v4l/buffer.rst > b/Documentation/media/uapi/v4l/buffer.rst > index ac58966ccb9b..ce46908bedfb 100644 > --- a/Documentation/media/uapi/v4l/buffer.rst > +++ b/Documentation/media/uapi/v4l/buffer.rst > @@ -34,6 +34,114 @@ flags are copied from the OUTPUT video buffer to the > CAPTURE video > buffer. > > > +Interactions between formats, controls and buffers > +== > + > +V4L2 exposes parameters that influence the buffer size, or the way data is > +laid out in the buffer. Those parameters are exposed through both formats and > +controls. One example of such a control is the ``V4L2_CID_ROTATE`` control > +that modifies the direction in which pixels are stored in the buffer, as well > +as the buffer size when the selected format includes padding at the end of > +lines. > + > +The set of information needed to interpret the content of a buffer (e.g. the > +pixel format, the line stride, the tiling orientation or the rotation) is > +collectively referred to in the rest of this section as the buffer layout. > + > +Modifying formats or controls that influence the buffer size or layout > require > +the stream to be stopped. Any attempt at such a modification while the stream > +is active shall cause the format or control set ioctl to return the ``EBUSY`` How about: s/the format or control set ioctl/the ioctl setting the format or the control/ > +error code. > + > +Controls that only influence the buffer layout can be modified at any time > +when the stream is stopped. As they don't influence the buffer size, no > +special handling is needed to synchronize those controls with buffer > +allocation. > + > +Formats and controls that influence the buffer size interact with buffer > +allocation. As buffer allocation is an expensive operation, drivers should > +allow format or controls that influence the buffer size to be changed with > +buffers allocated. A typical ioctl sequence to modify format and controls is > + > + #. VIDIOC_STREAMOFF > + #. VIDIOC_S_EXT_CTRLS > + #. VIDIOC_S_FMT > + #. VIDIOC_QBUF > + #. VIDIOC_STREAMON > + > +.. note:: > + > + The API doesn't mandate the above order for control (2.) and format (3.) > + changes. Format and controls can be set in a diff
Re: [PATCH v3 3/3] drm: rcar-du: Register a completion callback with VSP1
Hello! On 03/05/2017 07:00 PM, Kieran Bingham wrote: Currently we process page flip events on every display interrupt, however this does not take into consideration the processing time needed by the VSP1 utilised in the pipeline. Register a callback with the VSP driver to obtain completion events, and track them so that we only perform page flips when the full display pipeline has completed for the frame. Signed-off-by: Kieran Bingham [...] #endif /* __RCAR_DU_CRTC_H__ */ diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index b0ff304ce3dc..cbb6f54c99ef 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -28,6 +28,13 @@ #include "rcar_du_kms.h" #include "rcar_du_vsp.h" +static void rcar_du_vsp_complete(void *private) +{ + struct rcar_du_crtc *crtc = (struct rcar_du_crtc *)private; No need for explicit cast. + + rcar_du_crtc_finish_page_flip(crtc); +} + void rcar_du_vsp_enable(struct rcar_du_crtc *crtc) { const struct drm_display_mode *mode = &crtc->crtc.state->adjusted_mode; [...] MBR, Sergei
Re: [PATCH v6 3/3] ARM: dts: r7s72100: Add watchdog timer
On 03/04/2017 02:37 PM, Chris Brandt wrote: Add watchdog timer support for RZ/A1. For the RZ/A1, the only way to do a reset is to overflow the WDT, so this is useful even if you don't need the watchdog functionality. Signed-off-by: Chris Brandt Reviewed-by: Geert Uytterhoeven Acked-by: Guenter Roeck --- v4: * changed from timer@ to watchdog@ v3: * added Reviewed-by v2: * changed "renesas,r7s72100-reset" to "renesas,r7s72100-wdt" * changed "renesas,wdt-reset" to "renesas,rza-wdt" * added interupt property (even though it is not used) * added clocks property --- arch/arm/boot/dts/r7s72100.dtsi | 7 +++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/r7s72100.dtsi b/arch/arm/boot/dts/r7s72100.dtsi index ed62e19..22f96b7 100644 --- a/arch/arm/boot/dts/r7s72100.dtsi +++ b/arch/arm/boot/dts/r7s72100.dtsi @@ -382,6 +382,13 @@ cache-level = <2>; }; + wdt: watchdog@fcfe { + compatible = "renesas,r7s72100-wdt", "renesas,rza-wdt"; + reg = <0xfcfe 0x6>; + interrupts = ; + clocks = <&p0_clk>; + }; + i2c0: i2c@fcfee000 { #address-cells = <1>; #size-cells = <0>;
Re: [PATCH v6 2/3] watchdog: renesas-wdt: add support for rza
On 03/04/2017 02:37 PM, Chris Brandt wrote: Describe the WDT hardware in the RZ/A series. Signed-off-by: Chris Brandt Reviewed-by: Geert Uytterhoeven Acked-by: Rob Herring Reviewed-by: Guenter Roeck --- v3: * Add Acked-by, Reviewed-by. v2: * added to renesas-wdt.txt instead of creating a new file * changed commit title * added "renesas,rza-wdt" as a fallback * added interrupts property --- Documentation/devicetree/bindings/watchdog/renesas-wdt.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt b/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt index da24e31..9e306af 100644 --- a/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt +++ b/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt @@ -2,10 +2,11 @@ Renesas Watchdog Timer (WDT) Controller Required properties: - compatible : Should be "renesas,-wdt", and - "renesas,rcar-gen3-wdt" as fallback. + "renesas,rcar-gen3-wdt" or "renesas,rza-wdt" as fallback. Examples with soctypes are: - "renesas,r8a7795-wdt" (R-Car H3) - "renesas,r8a7796-wdt" (R-Car M3-W) +- "renesas,r7s72100-wdt" (RZ/A1) When compatible with the generic version, nodes must list the SoC-specific version corresponding to the platform first, followed by the generic @@ -17,6 +18,7 @@ Required properties: Optional properties: - timeout-sec : Contains the watchdog timeout in seconds - power-domains : the power domain the WDT belongs to +- interrupts: Some WDTs have an interrupt when used in interval timer mode Examples:
Re: [PATCH v6 1/3] watchdog: add rza_wdt driver
On 03/04/2017 02:37 PM, Chris Brandt wrote: Adds a watchdog timer driver for the Renesas RZ/A Series SoCs. A reset handler is also included since a WDT overflow is the only method for restarting an RZ/A SoC. Signed-off-by: Chris Brandt Reviewed-by: Guenter Roeck --- v3: * added #include * alphabetized #include list * removed call to platform_set_drvdata v2: * removed extra lines from file header comments * changed (1<<#) to BIT(#) * changed #define WTSCR_CKS(i) i to (i) * changed format to #define SOMETHINGvalue (and align values) * now check if clock rate < 16384 * added space before and after '/' for "(1000 * U8_MAX) / rate" * changed dev_info to dev_dbg for printing max_hw_heartbeat_ms * added watchdog_init_timeout() for user to set timeout in DT * switched to using devm_watchdog_register_device() * added error message if register fails * simplified rza_wdt_probe() return * removed function rza_wdt_remove() --- drivers/watchdog/Kconfig | 8 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/rza_wdt.c | 199 + 3 files changed, 208 insertions(+) create mode 100644 drivers/watchdog/rza_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index acb00b5..123c516 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -701,6 +701,14 @@ config RENESAS_WDT This driver adds watchdog support for the integrated watchdogs in the Renesas R-Car and other SH-Mobile SoCs (usually named RWDT or SWDT). +config RENESAS_RZAWDT + tristate "Renesas RZ/A WDT Watchdog" + depends on ARCH_RENESAS || COMPILE_TEST + select WATCHDOG_CORE + help + This driver adds watchdog support for the integrated watchdogs in the + Renesas RZ/A SoCs. These watchdogs can be used to reset a system. + config ASPEED_WATCHDOG tristate "Aspeed 2400 watchdog support" depends on ARCH_ASPEED || COMPILE_TEST diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 0c3d35e..84b897c 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -81,6 +81,7 @@ obj-$(CONFIG_LPC18XX_WATCHDOG) += lpc18xx_wdt.o obj-$(CONFIG_BCM7038_WDT) += bcm7038_wdt.o obj-$(CONFIG_ATLAS7_WATCHDOG) += atlas7_wdt.o obj-$(CONFIG_RENESAS_WDT) += renesas_wdt.o +obj-$(CONFIG_RENESAS_RZAWDT) += rza_wdt.o obj-$(CONFIG_ASPEED_WATCHDOG) += aspeed_wdt.o # AVR32 Architecture diff --git a/drivers/watchdog/rza_wdt.c b/drivers/watchdog/rza_wdt.c new file mode 100644 index 000..e618218 --- /dev/null +++ b/drivers/watchdog/rza_wdt.c @@ -0,0 +1,199 @@ +/* + * Renesas RZ/A Series WDT Driver + * + * Copyright (C) 2017 Renesas Electronics America, Inc. + * Copyright (C) 2017 Chris Brandt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DEFAULT_TIMEOUT30 + +/* Watchdog Timer Registers */ +#define WTCSR 0 +#define WTCSR_MAGIC0xA500 +#define WTSCR_WT BIT(6) +#define WTSCR_TME BIT(5) +#define WTSCR_CKS(i) (i) + +#define WTCNT 2 +#define WTCNT_MAGIC0x5A00 + +#define WRCSR 4 +#define WRCSR_MAGIC0x5A00 +#define WRCSR_RSTE BIT(6) +#define WRCSR_CLEAR_WOVF 0xA500 /* special value */ + +struct rza_wdt { + struct watchdog_device wdev; + void __iomem *base; + struct clk *clk; +}; + +static int rza_wdt_start(struct watchdog_device *wdev) +{ + struct rza_wdt *priv = watchdog_get_drvdata(wdev); + + /* Stop timer */ + writew(WTCSR_MAGIC | 0, priv->base + WTCSR); + + /* Must dummy read WRCSR:WOVF at least once before clearing */ + readb(priv->base + WRCSR); + writew(WRCSR_CLEAR_WOVF, priv->base + WRCSR); + + /* +* Start timer with slowest clock source and reset option enabled. +*/ + writew(WRCSR_MAGIC | WRCSR_RSTE, priv->base + WRCSR); + writew(WTCNT_MAGIC | 0, priv->base + WTCNT); + writew(WTCSR_MAGIC | WTSCR_WT | WTSCR_TME | WTSCR_CKS(7), + priv->base + WTCSR); + + return 0; +} + +static int rza_wdt_stop(struct watchdog_device *wdev) +{ + struct rza_wdt *priv = watchdog_get_drvdata(wdev); + + writew(WTCSR_MAGIC | 0, priv->base + WTCSR); + + return 0; +} + +static int rza_wdt_ping(struct watchdog_device *wdev) +{ + struct rza_wdt *priv = watchdog_get_drvdata(wdev); + + writew(WTCNT_MAGIC | 0, priv->base + WTCNT); + + return 0; +} + +static int rza_wdt_restart(struct watchdog_device *wdev, unsigned long action, + void *data) +{ + struct rza_wdt *priv = watchdog_get_drvdata(wdev); + + /* Stop timer */ + writew(WTCSR_MAGIC | 0, priv->base
[PATCH v3 3/3] drm: rcar-du: Register a completion callback with VSP1
Currently we process page flip events on every display interrupt, however this does not take into consideration the processing time needed by the VSP1 utilised in the pipeline. Register a callback with the VSP driver to obtain completion events, and track them so that we only perform page flips when the full display pipeline has completed for the frame. Signed-off-by: Kieran Bingham --- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 8 ++-- drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 1 + drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 9 + 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index 2aceb84fc15d..c1812e20 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -299,7 +299,7 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc) * Page Flip */ -static void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc) +void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc) { struct drm_pending_vblank_event *event; struct drm_device *dev = rcrtc->crtc.dev; @@ -571,6 +571,7 @@ static const struct drm_crtc_funcs crtc_funcs = { static irqreturn_t rcar_du_crtc_irq(int irq, void *arg) { struct rcar_du_crtc *rcrtc = arg; + struct rcar_du_device *rcdu = rcrtc->group->dev; irqreturn_t ret = IRQ_NONE; u32 status; @@ -579,7 +580,10 @@ static irqreturn_t rcar_du_crtc_irq(int irq, void *arg) if (status & DSSR_FRM) { drm_crtc_handle_vblank(&rcrtc->crtc); - rcar_du_crtc_finish_page_flip(rcrtc); + + if (rcdu->info->gen < 3) + rcar_du_crtc_finish_page_flip(rcrtc); + ret = IRQ_HANDLED; } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h index a7194812997e..ebdbff9d8e59 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h @@ -71,5 +71,6 @@ void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc); void rcar_du_crtc_route_output(struct drm_crtc *crtc, enum rcar_du_output output); +void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc); #endif /* __RCAR_DU_CRTC_H__ */ diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index b0ff304ce3dc..cbb6f54c99ef 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -28,6 +28,13 @@ #include "rcar_du_kms.h" #include "rcar_du_vsp.h" +static void rcar_du_vsp_complete(void *private) +{ + struct rcar_du_crtc *crtc = (struct rcar_du_crtc *)private; + + rcar_du_crtc_finish_page_flip(crtc); +} + void rcar_du_vsp_enable(struct rcar_du_crtc *crtc) { const struct drm_display_mode *mode = &crtc->crtc.state->adjusted_mode; @@ -35,6 +42,8 @@ void rcar_du_vsp_enable(struct rcar_du_crtc *crtc) struct vsp1_du_lif_config cfg = { .width = mode->hdisplay, .height = mode->vdisplay, + .callback = rcar_du_vsp_complete, + .callback_data = crtc, }; struct rcar_du_plane_state state = { .state = { -- git-series 0.9.1
[PATCH v3 2/3] v4l: vsp1: Extend VSP1 module API to allow DRM callbacks
To be able to perform page flips in DRM without flicker we need to be able to notify the rcar-du module when the VSP has completed its processing. We must not have bidirectional dependencies on the two components to maintain support for loadable modules, thus we extend the API to allow a callback to be registered within the VSP DRM interface. Signed-off-by: Kieran Bingham --- drivers/media/platform/vsp1/vsp1_drm.c | 17 + drivers/media/platform/vsp1/vsp1_drm.h | 11 +++ include/media/vsp1.h | 13 + 3 files changed, 41 insertions(+) diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index 4ee437c7ff0c..d93bf7d3a39e 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -37,6 +37,14 @@ void vsp1_drm_display_start(struct vsp1_device *vsp1) vsp1_dlm_irq_display_start(vsp1->drm->pipe.output->dlm); } +static void vsp1_du_pipeline_frame_end(struct vsp1_pipeline *pipe) +{ + struct vsp1_drm *drm = to_vsp1_drm(pipe); + + if (drm->du_complete) + drm->du_complete(drm->du_private); +} + /* - * DU Driver API */ @@ -96,6 +104,7 @@ int vsp1_du_setup_lif(struct device *dev, const struct vsp1_du_lif_config *cfg) } pipe->num_inputs = 0; + vsp1->drm->du_complete = NULL; vsp1_dlm_reset(pipe->output->dlm); vsp1_device_put(vsp1); @@ -200,6 +209,13 @@ int vsp1_du_setup_lif(struct device *dev, const struct vsp1_du_lif_config *cfg) if (ret < 0) return ret; + /* +* Register a callback to allow us to notify the DRM framework of frame +* completion events. +*/ + vsp1->drm->du_complete = cfg->callback; + vsp1->drm->du_private = cfg->callback_data; + ret = media_pipeline_start(&pipe->output->entity.subdev.entity, &pipe->pipe); if (ret < 0) { @@ -607,6 +623,7 @@ int vsp1_drm_init(struct vsp1_device *vsp1) pipe->lif = &vsp1->lif->entity; pipe->output = vsp1->wpf[0]; pipe->output->pipe = pipe; + pipe->frame_end = vsp1_du_pipeline_frame_end; return 0; } diff --git a/drivers/media/platform/vsp1/vsp1_drm.h b/drivers/media/platform/vsp1/vsp1_drm.h index c8d2f88fc483..3de2095cb0ce 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.h +++ b/drivers/media/platform/vsp1/vsp1_drm.h @@ -23,6 +23,8 @@ * @num_inputs: number of active pipeline inputs at the beginning of an update * @inputs: source crop rectangle, destination compose rectangle and z-order * position for every input + * @du_complete: frame completion callback for the DU driver (optional) + * @du_private: data to be passed to the du_complete callback */ struct vsp1_drm { struct vsp1_pipeline pipe; @@ -33,8 +35,17 @@ struct vsp1_drm { struct v4l2_rect compose; unsigned int zpos; } inputs[VSP1_MAX_RPF]; + + /* Frame syncronisation */ + void (*du_complete)(void *); + void *du_private; }; +static inline struct vsp1_drm *to_vsp1_drm(struct vsp1_pipeline *pipe) +{ + return container_of(pipe, struct vsp1_drm, pipe); +} + int vsp1_drm_init(struct vsp1_device *vsp1); void vsp1_drm_cleanup(struct vsp1_device *vsp1); int vsp1_drm_create_links(struct vsp1_device *vsp1); diff --git a/include/media/vsp1.h b/include/media/vsp1.h index bfc701f04f3f..d59d0adf560d 100644 --- a/include/media/vsp1.h +++ b/include/media/vsp1.h @@ -20,9 +20,22 @@ struct device; int vsp1_du_init(struct device *dev); +/** + * struct vsp1_du_lif_config - VSP LIF configuration + * @width: output frame width + * @height: output frame height + * @callback: frame completion callback function (optional) + * @callback_data: data to be passed to the frame completion callback + * + * When the optional callback is provided to the VSP1, the VSP1 must guarantee + * that one completion callback is performed after every vsp1_du_atomic_flush() + */ struct vsp1_du_lif_config { unsigned int width; unsigned int height; + + void (*callback)(void *); + void *callback_data; }; int vsp1_du_setup_lif(struct device *dev, const struct vsp1_du_lif_config *cfg); -- git-series 0.9.1
[PATCH v3 0/3] RCAR-DU, VSP1: Prevent pre-emptive frame flips on VSP1-DRM pipelines
The RCAR-DU utilises a running VSPD pipeline to perform processing for the display pipeline. This presents the opportunity for some race conditions to affect the quality of the display output. To prevent reporting page flips early, we must track this timing through the VSP1, and only allow the rcar-du object to report the page-flip completion event after the VSP1 has processed. This series ensures that tearing and flicker is prevented, without introducing the performance impact mentioned in the previous series. [PATCH 1/3] handles potential race conditions in vsp1_dlm_irq_frame_end() and prevents signalling the frame end in this event. [PATCH 2/3] extends the VSP1 to allow a callback to be registered giving the VSP1 the ability to notify completion events. [PATCH 3/3] utilises the callback extension to send page flips at the end of VSP processing for Gen3 platforms. These patches have been tested by introducing artificial delays in the commit code paths and verifying that no visual tearing or flickering occurs. Extensive testing around the race window has been performed by dynamically adapting the artificial delay between 10, and 17 seconds in 100uS increments for periods of 5 seconds on each delay test. These tests have successfully run for 3 hours. Manual start/stop testing has also been performed. Kieran Bingham (3): v4l: vsp1: Postpone frame end handling in event of display list race v4l: vsp1: Extend VSP1 module API to allow DRM callbacks drm: rcar-du: Register a completion callback with VSP1 drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 8 ++-- drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 1 + drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 9 + drivers/media/platform/vsp1/vsp1_dl.c | 19 +-- drivers/media/platform/vsp1/vsp1_dl.h | 2 +- drivers/media/platform/vsp1/vsp1_drm.c | 17 + drivers/media/platform/vsp1/vsp1_drm.h | 11 +++ drivers/media/platform/vsp1/vsp1_pipe.c | 13 - include/media/vsp1.h| 13 + 9 files changed, 87 insertions(+), 6 deletions(-) base-commit: cdb5795cbc4ddbe5082c25c52ebc1d811ac3849e -- git-series 0.9.1
[PATCH v3 1/3] v4l: vsp1: Postpone frame end handling in event of display list race
If we try to commit the display list while an update is pending, we have missed our opportunity. The display list manager will hold the commit until the next interrupt. In this event, we skip the pipeline completion callback handler so that the pipeline will not mistakenly report frame completion to the user. Signed-off-by: Kieran Bingham --- drivers/media/platform/vsp1/vsp1_dl.c | 19 +-- drivers/media/platform/vsp1/vsp1_dl.h | 2 +- drivers/media/platform/vsp1/vsp1_pipe.c | 13 - 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c index b9e5027778ff..f449ca689554 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.c +++ b/drivers/media/platform/vsp1/vsp1_dl.c @@ -562,9 +562,19 @@ void vsp1_dlm_irq_display_start(struct vsp1_dl_manager *dlm) spin_unlock(&dlm->lock); } -void vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm) +/** + * vsp1_dlm_irq_frame_end - Display list handler for the frame end interrupt + * @dlm: the display list manager + * + * Return true if the previous display list has completed at frame end, or false + * if it has been delayed by one frame because the display list commit raced + * with the frame end interrupt. The function always returns true in header mode + * as display list processing is then not continuous and races never occur. + */ +bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm) { struct vsp1_device *vsp1 = dlm->vsp1; + bool completed = false; spin_lock(&dlm->lock); @@ -576,8 +586,10 @@ void vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm) * perform any operation as there can't be any new display list queued * in that case. */ - if (dlm->mode == VSP1_DL_MODE_HEADER) + if (dlm->mode == VSP1_DL_MODE_HEADER) { + completed = true; goto done; + } /* * The UPD bit set indicates that the commit operation raced with the @@ -597,6 +609,7 @@ void vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm) if (dlm->queued) { dlm->active = dlm->queued; dlm->queued = NULL; + completed = true; } /* @@ -619,6 +632,8 @@ void vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm) done: spin_unlock(&dlm->lock); + + return completed; } /* Hardware Setup */ diff --git a/drivers/media/platform/vsp1/vsp1_dl.h b/drivers/media/platform/vsp1/vsp1_dl.h index 7131aa3c5978..6ec1380a10af 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.h +++ b/drivers/media/platform/vsp1/vsp1_dl.h @@ -28,7 +28,7 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1, void vsp1_dlm_destroy(struct vsp1_dl_manager *dlm); void vsp1_dlm_reset(struct vsp1_dl_manager *dlm); void vsp1_dlm_irq_display_start(struct vsp1_dl_manager *dlm); -void vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm); +bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm); struct vsp1_dl_list *vsp1_dl_list_get(struct vsp1_dl_manager *dlm); void vsp1_dl_list_put(struct vsp1_dl_list *dl); diff --git a/drivers/media/platform/vsp1/vsp1_pipe.c b/drivers/media/platform/vsp1/vsp1_pipe.c index 35364f594e19..d15327701ad8 100644 --- a/drivers/media/platform/vsp1/vsp1_pipe.c +++ b/drivers/media/platform/vsp1/vsp1_pipe.c @@ -304,10 +304,21 @@ bool vsp1_pipeline_ready(struct vsp1_pipeline *pipe) void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe) { + bool completed; + if (pipe == NULL) return; - vsp1_dlm_irq_frame_end(pipe->output->dlm); + completed = vsp1_dlm_irq_frame_end(pipe->output->dlm); + if (!completed) { + /* +* If the DL commit raced with the frame end interrupt, the +* commit ends up being postponed by one frame. Return +* immediately without calling the pipeline's frame end handler +* or incrementing the sequence number. +*/ + return; + } if (pipe->frame_end) pipe->frame_end(pipe); -- git-series 0.9.1
[PATCH v2.1] v4l: Clearly document interactions between formats, controls and buffers
V4L2 exposes parameters that influence buffers sizes through the format ioctls (VIDIOC_G_FMT, VIDIOC_TRY_FMT, VIDIOC_S_FMT, and possibly VIDIOC_G_SELECTION and VIDIOC_S_SELECTION). Other parameters not part of the format structure may also influence buffer sizes or buffer layout in general. One existing such parameter is rotation, which is implemented by the VIDIOC_ROTATE control and thus exposed through the V4L2 control ioctls. The interaction between those parameters and buffers is currently only partially specified by the V4L2 API. In particular interactions between controls and buffers isn't specified at all. The behaviour of the VIDIOC_S_FMT and VIDIOC_S_SELECTION ioctls when buffers are allocated is also not fully specified. This commit clearly defines and documents the interactions between formats, selections, controls and buffers. The preparatory discussions for the documentation change considered completely disallowing controls that change the buffer size or layout, in favour of extending the format API with a new ioctl that would bundle those controls with format information. The idea has been rejected, as this would essentially be a restricted version of the upcoming request API that wouldn't bring any additional value. Another option we have considered was to mandate the use of the request API to modify controls that influence buffer size or layout. This has also been rejected on the grounds that requiring the request API to change rotation even when streaming is stopped would significantly complicate implementation of drivers and usage of the V4L2 API for applications. Applications will however be required to use the upcoming request API to change at runtime formats or controls that influence the buffer size or layout, because of the need to synchronize buffers with the formats and controls. Otherwise there would be no way to interpret the content of a buffer correctly. Signed-off-by: Laurent Pinchart --- Changes since v2: - Document the interaction with ioctls that can affect formats (VIDIOC_S_SELECTION, VIDIOC_S_INPUT, VIDIOC_S_OUTPUT, VIDIOC_S_STD and VIDIOC_S_DV_TIMINGS) - Clarify the format/control change order --- Documentation/media/uapi/v4l/buffer.rst | 108 1 file changed, 108 insertions(+) diff --git a/Documentation/media/uapi/v4l/buffer.rst b/Documentation/media/uapi/v4l/buffer.rst index ac58966ccb9b..ce46908bedfb 100644 --- a/Documentation/media/uapi/v4l/buffer.rst +++ b/Documentation/media/uapi/v4l/buffer.rst @@ -34,6 +34,114 @@ flags are copied from the OUTPUT video buffer to the CAPTURE video buffer. +Interactions between formats, controls and buffers +== + +V4L2 exposes parameters that influence the buffer size, or the way data is +laid out in the buffer. Those parameters are exposed through both formats and +controls. One example of such a control is the ``V4L2_CID_ROTATE`` control +that modifies the direction in which pixels are stored in the buffer, as well +as the buffer size when the selected format includes padding at the end of +lines. + +The set of information needed to interpret the content of a buffer (e.g. the +pixel format, the line stride, the tiling orientation or the rotation) is +collectively referred to in the rest of this section as the buffer layout. + +Modifying formats or controls that influence the buffer size or layout require +the stream to be stopped. Any attempt at such a modification while the stream +is active shall cause the format or control set ioctl to return the ``EBUSY`` +error code. + +Controls that only influence the buffer layout can be modified at any time +when the stream is stopped. As they don't influence the buffer size, no +special handling is needed to synchronize those controls with buffer +allocation. + +Formats and controls that influence the buffer size interact with buffer +allocation. As buffer allocation is an expensive operation, drivers should +allow format or controls that influence the buffer size to be changed with +buffers allocated. A typical ioctl sequence to modify format and controls is + + #. VIDIOC_STREAMOFF + #. VIDIOC_S_EXT_CTRLS + #. VIDIOC_S_FMT + #. VIDIOC_QBUF + #. VIDIOC_STREAMON + +.. note:: + + The API doesn't mandate the above order for control (2.) and format (3.) + changes. Format and controls can be set in a different order, or even + interleaved, depending on the device and use case. For instance some + controls might behave differently for different pixel formats, in which + case the format might need to be set first. + +Queued buffers must be large enough for the new format or controls. + +Drivers shall return a ``ENOSPC`` error in response to format change +(:c:func:`VIDIOC_S_FMT`) or control changes (:c:func:`VIDIOC_S_CTRL` or +:c:func:`VIDIOC_S_EXT_CTRLS`) if buffers too small for the new format are +currently queued. As a simplification, drivers are allowed to return an error +from thes
Re: [PATCH v2 2/3] v4l: Clearly document interactions between formats, controls and buffers
Hi Hans, On Saturday 04 Mar 2017 11:53:45 Hans Verkuil wrote: > On 28/02/17 16:03, Laurent Pinchart wrote: > > V4L2 exposes parameters that influence buffers sizes through the format > > ioctls (VIDIOC_G_FMT, VIDIOC_TRY_FMT and VIDIO_S_FMT). Other parameters > > S_SELECTION should be mentioned here as well (more about that later). I'll update that according to the conversation we had on IRC about this topic. > > not part of the format structure may also influence buffer sizes or > > buffer layout in general. One existing such parameter is rotation, which > > is implemented by the VIDIOC_ROTATE control and thus exposed through the > > V4L2 control ioctls. > > > > The interaction between those parameters and buffers is currently only > > partially specified by the V4L2 API. In particular interactions between > > controls and buffers isn't specified at all. The behaviour of the > > VIDIOC_S_FMT ioctl when buffers are allocated is also not fully > > specified. > > > > This commit clearly defines and documents the interactions between > > formats, controls and buffers. > > > > The preparatory discussions for the documentation change considered > > completely disallowing controls that change the buffer size or layout, > > in favour of extending the format API with a new ioctl that would bundle > > those controls with format information. The idea has been rejected, as > > this would essentially be a restricted version of the upcoming request > > API that wouldn't bring any additional value. > > > > Another option we have considered was to mandate the use of the request > > API to modify controls that influence buffer size or layout. This has > > also been rejected on the grounds that requiring the request API to > > change rotation even when streaming is stopped would significantly > > complicate implementation of drivers and usage of the V4L2 API for > > applications. > > > > Applications will however be required to use the upcoming request API to > > change at runtime formats or controls that influence the buffer size or > > layout, because of the need to synchronize buffers with the formats and > > controls. Otherwise there would be no way to interpret the content of a > > buffer correctly. > > > > Signed-off-by: Laurent Pinchart > > > > --- > > > > Documentation/media/uapi/v4l/buffer.rst | 88 > > 1 file changed, 88 insertions(+) > > > > diff --git a/Documentation/media/uapi/v4l/buffer.rst > > b/Documentation/media/uapi/v4l/buffer.rst index > > ac58966ccb9b..5c58db98ab7a 100644 > > --- a/Documentation/media/uapi/v4l/buffer.rst > > +++ b/Documentation/media/uapi/v4l/buffer.rst > > @@ -34,6 +34,94 @@ flags are copied from the OUTPUT video buffer to the > > CAPTURE video> > > buffer. > > > > +Interactions between formats, controls and buffers > > +== > > + > > +V4L2 exposes parameters that influence the buffer size, or the way data > > is > > +laid out in the buffer. Those parameters are exposed through both formats > > and +controls. One example of such a control is the ``V4L2_CID_ROTATE`` > > control +that modifies the direction in which pixels are stored in the > > buffer, as well +as the buffer size when the selected format includes > > padding at the end of +lines. > > + > > +The set of information needed to interpret the content of a buffer (e.g. > > the +pixel format, the line stride, the tiling orientation or the > > rotation) is +collectively referred to in the rest of this section as the > > buffer layout. + > > +Modifying formats or controls that influence the buffer size or layout > > require +the stream to be stopped. Any attempt at such a modification > > while the stream +is active shall cause the format or control set ioctl > > to return the ``EBUSY`` +error code. > > This is not what happens today: it's not the streaming part that causes > EBUSY to be returned but whether or not buffers are allocated. Note that this patch documents the recommended behaviour we want to achieve. It can differ from the behaviour implemented today as long as today's behaviour (at least the behaviour of the drivers that we don't consider as non-compliant, which is the vast majority) is not contradicted by this patch. In other words, we can recommend here a more generic versatile and powerful behaviour as long as the more restricted behaviour implemented today is also allowed. > Today we do not support changing buffer sizes on the fly, so any attempt to > call an ioctl that would change the buffer size is blocked and EBUSY is > returned. To be precise: drivers call vb2_is_busy() to determine this. > > To my knowledge all vb2-using drivers behave like this. There may be old > drivers that do not do this (and these have a high likelyhood of being > wrong). Please also note that the above description doesn't contradict the behaviour implemented today. It explains that changing formats and controls is not allowed whi
Re: [PATCH v2 2/3] v4l: Clearly document interactions between formats, controls and buffers
Hi Sakari, On Saturday 04 Mar 2017 15:48:54 Sakari Ailus wrote: > On Sat, Mar 04, 2017 at 11:57:32AM +0100, Hans Verkuil wrote: > ... > > >>> +To simplify their implementation, drivers may also require buffers to > >>> be +reallocated in order to change formats or controls that influence > >>> the buffer +size. In that case, to perform such changes, userspace > >>> applications shall +first stop the video stream with the > >>> :c:func:`VIDIOC_STREAMOFF` ioctl if it +is running and free all buffers > >>> with the :c:func:`VIDIOC_REQBUFS` ioctl if +they are allocated. The > >>> format or controls can then be modified, and buffers +shall then be > >>> reallocated and the stream restarted. A typical ioctl sequence +is > >>> + > >>> + #. VIDIOC_STREAMOFF > >>> + #. VIDIOC_REQBUFS(0) > >>> + #. VIDIOC_S_FMT > >>> + #. VIDIOC_S_EXT_CTRLS > >> > >> Same here. > >> > >> Would it be safe to say that controls are changed first? I wonder if > >> there could be special cases where this wouldn't apply though. It could > >> ultimately come down to hardware features: rotation might be only > >> available for certain formats so you'd need to change the format first > >> to enable rotation. > >> > >> What you're documenting above is a typical sequence so it doesn't have to > >> be applicable to all potential hardware. I might mention there could be > >> such dependencies. I wonder if one exists at the moment. No? > > > > The way V4L2 works is that the last ioctl called gets 'preference'. So the > > driver should attempt to satisfy the ioctl, even if that means undoing > > previous ioctls. In other words, V4L2 allows any order, but the > > end-result might be different depending on the hardware capabilities. > > Indeed. But the above sequence suggests that formats are set before > controls. I suggested to clarify that part. I agree with both of you. I'll clarify that this is just an example and that formats and controls can be set in a different order (or even interleaved). -- Regards, Laurent Pinchart
Re: [PATCH 0/4] iio: adc: Maxim max961x driver
On 27/02/17 09:09, jacopo mondi wrote: > Hi Jonathan, > On 25/02/2017 17:09, Jonathan Cameron wrote: >> On 24/02/17 15:05, Jacopo Mondi wrote: >>> Hello! >>> >>> This series adds driver and documentation for Maxim max9611/max9612 >>> high-side current sense amplifier with 12-bit ADC and I2c interface. >>> It also registers two devices installed on VDD_0.8V and DVFS_0.8V lines >>> in Renesas r87796 Salvator-X board. >>> >>> The device provides several functionalities, and only some of them are >>> currently supported by this driver. >>> Particularly, the on-board op-amp and analog comparator are not currently >>> supported. >> More fun to come ;) >>> >>> A simplified integration schematic drawing is here reported: >>> >>> o/\/\/-o---|LOAD|--- >>> |shunt | >>> |__|___ >>> | RS+RS- | >>> | |-gain-| | >>> | | | >>> | | | >>> |max961x |->| ADC |= I2c >>> |__| >>> >>> >>> The device provides though its 12-bits ADC the following informations: >> information is it's own plural (silly English quirk of the day!) >> >>> - Common input voltage on RS+ >>> - Voltage drop between RS+ and RS- ends >>> - Die temperature >>> >>> All of the above ones are exposed though IIO with _raw and _scale values >>> (plus _input for milli degree Celsius die temperature). >>> >>> From the above values the driver calculates the current flowing between >>> RS+ and RS- ends, using the shunt resistor value provided by device tree, >>> and >>> the power load. Again this values are exposed through _raw and _scale >>> attributes, which I'm not completely sure it's acceptables as they are >>> calculated values and not natively provided by the current sense amplifier. >>> I would like to hear IIO people opinions on this, if they should be better >>> exposed though some other attributes which are not _raw and _scale, or if >>> their calculation should be completely left to userspace tools. >> So one element of the implementation is a problem. >> Because of the dynamic gain adjustment you are doing in the driver (which I >> rather like BTW) there will be instabilities in the computed values that >> userspace comes up with when we are near a transition for in the current >> sense amplifier gain. We can't do that as crazy outputs will result >> (read offset and scale for possible different values of that gain then >> read the actual ADC value for a possible 3rd choice resulting in complete >> garbage). >> >> So there are two ways to avoid this: >> 1. Move all that magic into the original reads and apply the gain and offset >> before they get to userspace. >> 2. Provide enough information for userspace to be able to compute everything >> iff it is using buffered mode with a 'scan' covering all the channels in one >> go. Even then we'd have to explicitly allow reading of the PGA gain as a >> channel, or make userspace responsible for doing your autogain stuff. >> >> 1 is probably easier but will make implementing 2 as a follow up will be >> tricky >> and would be needed if you want to read this stuff faster than sysfs will >> allow. >> >> It's a shame, but my gut feeling is you want to drop the autogain stuff >> as then it all becomes straight forward. >> >> What do others think? >> > > Just to add the following element to the discussion. > > The device supports cycling between channels by itself, sequentially cycling > between them every 2 msec. > At the same time, gain setting is not involved in this procedure, and last > applied is used on current sense voltage channel. > > Still this does not help with un-synchronized reads of gain-dependent values, > as offset and scale are. > > Also, removing auto-gain setting routine will simplify stuff, but I don't see > how all becomes straight forward then. I mean, if we keep gain at a fixed > value, yes everything's easier, but it will work under a much more limited > pre-conditions set... You'd be moving the issue to userspace. This would be beneficial if you were looking to use the buffered interfaces (through a kfifo). In those cases processed values are often a non starter as they don't have well defined 'sizes' in the same way that a reading directly from the chip does. So under those circumstances, your userspace code might elect to modify the gain to get in the 'right' region only at startup, or after some initial 'calibration data capture'. Then it could merily stream data out without caring about it. To run remotely fast and consistenty you'd have to stop doing the multiple passes needed for autogain. However, if that interface never makes sense for this device anyway then it the approach of doing it all in kernel makes more sense. With a 500sps device like this it's on the boundary to my mind... Quick enough that using the chardev access makes sense, but the usecase is perhaps such that we should leave this all in kernel space. It's
Re: [PATCH] media: platform: Renesas IMR driver
Hi Sergei, Thanks for your efforts with this driver. Nice to see that V2 is getting in better shape. In the future, would it be possible for you to include the patch version number in the [PATCH] tag somehow? On Fri, Mar 3, 2017 at 9:03 PM, Sergei Shtylyov wrote: > On 03/03/2017 02:58 PM, Geert Uytterhoeven wrote: > > + - "renesas,imr-lx4-v3m" for R-Car V3M. "renesas,-EPROBE_DEFER-imr-lx4" >>> >>> >>> >>>Huh? :-) >> >> >> Do you know the part number of V3M? > > >No, but using the names from the manual I don't need it. NAK, like Geert says, please follow the same style as other upstream drivers. DT compat strings is not a place for random polices. Thanks, / magnus
Re: [PATCH 3/4] iio: adc: Add max9611/9612 ADC driver
On 27/02/17 07:45, jacopo mondi wrote: > Hi Jonathan, >thanks for review > > On 25/02/2017 16:53, Jonathan Cameron wrote: >> On 24/02/17 15:05, Jacopo Mondi wrote: >>> Add iio driver for Maxim max9611/9612 current-sense amplifiers with >>> 12-bits ADC. >> Data sheet link always good >>> >>> Signed-off-by: Jacopo Mondi >> I'm going to respond to the cover letter wrt to providing dynamic scales >> and offsets in a moment as you raised the question there. >> >> Otherwise, various bits and bobs inline. >> >> Interesting part to handle as it can read a lot of values that are useful >> only >> after some magic calculations are done. >> >> Jonathan >>> --- >>> drivers/iio/adc/Kconfig | 10 + >>> drivers/iio/adc/Makefile | 1 + >>> drivers/iio/adc/max961x.c | 648 >>> ++ >>> 3 files changed, 659 insertions(+) >>> create mode 100644 drivers/iio/adc/max961x.c >>> >>> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig >>> index dedae7a..f86026a 100644 >>> --- a/drivers/iio/adc/Kconfig >>> +++ b/drivers/iio/adc/Kconfig >>> @@ -354,6 +354,16 @@ config MAX1363 >>>To compile this driver as a module, choose M here: the module will be >>>called max1363. >>> >>> +configMAX961x >>> +tristate "Maxim max9611/9612 ADC driver" >>> +depends on I2C >>> +help >>> + Say yes here to build support for Maxim max9611/9612 current sense >>> + amplifiers with 12-bits ADC interface. >>> + >>> + To compile this driver as a module, choose M here: the module will be >>> + called max961x. >>> + >>> config MCP320X >>> tristate "Microchip Technology MCP3x01/02/04/08" >>> depends on SPI >>> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile >>> index d001262..ff19250 100644 >>> --- a/drivers/iio/adc/Makefile >>> +++ b/drivers/iio/adc/Makefile >>> @@ -34,6 +34,7 @@ obj-$(CONFIG_LTC2485) += ltc2485.o >>> obj-$(CONFIG_MAX1027) += max1027.o >>> obj-$(CONFIG_MAX11100) += max11100.o >>> obj-$(CONFIG_MAX1363) += max1363.o >>> +obj-$(CONFIG_MAX961x) += max961x.o >>> obj-$(CONFIG_MCP320X) += mcp320x.o >>> obj-$(CONFIG_MCP3422) += mcp3422.o >>> obj-$(CONFIG_MEDIATEK_MT6577_AUXADC) += mt6577_auxadc.o >>> diff --git a/drivers/iio/adc/max961x.c b/drivers/iio/adc/max961x.c >>> new file mode 100644 >>> index 000..a544e69 >>> --- /dev/null >>> +++ b/drivers/iio/adc/max961x.c >>> @@ -0,0 +1,648 @@ >>> +/* >>> + * iio/adc/max961x.c >>> + * >>> + * Maxim max9611/9612 high side current sense amplifier with >>> + * 12-bit ADC interface. >>> + * >>> + * Copyright (C) 2017 Jacopo Mondi >>> + * >>> + * This program is free software; you can redistribute it and/or modify >>> + * it under the terms of the GNU General Public License version 2 as >>> + * published by the Free Software Foundation. >>> + */ >>> + >>> +/* >>> + * This driver supports input common-mode voltage, current-sense >>> + * amplifier with programmable gains and die temperature reading from >>> + * Maxim max9611/9612. >>> + * Op-amp, analog comparator, and watchdog functionalities are not >>> + * supported by this driver. >>> + */ >>> + >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> + >>> +#define DRIVER_NAME "max961x" >>> + >>> +/* max961x register addresses */ >> Prefix these with MAX9611_ to avoid possible clashes in future. >> > > I initially did, then removed that to counterbalance my tendency to be a bit > verbose in naming stuff. > > I'll use the MAX9611_ prefix where appropriate > >>> +#define REG_CSA_DATA0x00 > [snip >>> + .info_mask_separate= BIT(IIO_CHAN_INFO_RAW) | >>> + BIT(IIO_CHAN_INFO_SCALE) | >> The only cases we normally allow bother raw and processed output in >> are ones where we are supporting some defunct (i.e. wrong usage) in the >> userspace ABI. So drop the processed path please. > > Will do > >> >>> + BIT(IIO_CHAN_INFO_PROCESSED), >>> + .address= MAX961x_CHAN_TEMPERATURE, >>> +}, >>> +{ /* [1] common voltage input */ >>> + .type= IIO_VOLTAGE, >>> + .info_mask_separate= BIT(IIO_CHAN_INFO_RAW) | >>> + BIT(IIO_CHAN_INFO_SCALE) | >>> + BIT(IIO_CHAN_INFO_OFFSET), >>> + .address= MAX961x_CHAN_VOLTAGE_INPUT, >>> + .channel= MAX961x_CHAN_VOLTAGE_INPUT, >> For the channel it would be easier to read perhaps if you just put >> the 0 in directly here. >>> + .indexed= 1, >>> +}, >>> +{ /* [2] current sense amplifier voltage output */ >>> + .type= IIO_VOLTAGE, >>> + .info_mask_separate= BIT(IIO_CHAN_INFO_RAW) | >>> + BIT(IIO_CHAN_INFO_SCALE) | >>> + BIT(IIO_CHAN_INFO_OFFSET), >>> + .address= MAX961x_CHAN_VOLTAGE_SENSE, >>> + .channel= MAX961x_CHAN_VOLTAGE_SENSE, >>> + .indexed= 1, >>> +}, >> >> As you say, the next o