All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH/RFC v3 00/19] Common Display Framework
@ 2013-08-09 17:14 Laurent Pinchart
  2013-08-09 17:14 ` [PATCH/RFC v3 01/19] OMAPDSS: panels: Rename Kconfig options to OMAP2_DISPLAY_* Laurent Pinchart
                   ` (21 more replies)
  0 siblings, 22 replies; 83+ messages in thread
From: Laurent Pinchart @ 2013-08-09 17:14 UTC (permalink / raw)
  To: dri-devel, linux-fbdev, linux-media
  Cc: Sebastien Guiriec, Jesse Barnes, Benjamin Gaignard, Tom Gall,
	Kyungmin Park, Tomi Valkeinen, Stephen Warren, Mark Zhang,
	Stéphane Marchesin, Alexandre Courbot, Ragesh Radhakrishnan,
	Thomas Petazzoni, Sunil Joshi, Maxime Ripard, Vikas Sajjan,
	Marcus Lorentzon

Hi everybody,

Here's the third RFC of the Common Display Framework.

I won't repeat all the background information from the versions one and two
here, you can read it at http://lwn.net/Articles/512363/ and
http://lwn.net/Articles/526965/.

This RFC isn't final. Given the high interest in CDF and the urgent tasks that
kept delaying the next version of the patch set, I've decided to release v3
before completing all parts of the implementation. Known missing items are

- documentation: kerneldoc and this cover letter should provide basic
  information, more extensive documentation will likely make it to v4.

- pipeline configuration and control: generic code to configure and control
  display pipelines (in a nutshell, translating high-level mode setting and
  DPMS calls to low-level entity operations) is missing. Video and stream
  control operations have been carried over from v2, but will need to be
  revised for v4.

- DSI support: I still have no DSI hardware I can easily test the code on.

Special thanks go to

- Renesas for inviting me to LinuxCon Japan 2013 where I had the opportunity
  to validate the CDF v3 concepts with Alexandre Courbot (NVidia) and Tomasz
  Figa (Samsung).

- Tomi Valkeinen (TI) for taking the time to deeply brainstorm v3 with me.

- Linaro for inviting me to Linaro Connect Europe 2013, the discussions we had
  there greatly helped moving CDF forward.

- And of course all the developers who showed interest in CDF and spent time
  sharing ideas, reviewing patches and testing code.

I have to confess I was a bit lost and discouraged after all the CDF-related
meetings during which we have discussed how to move from v2 to v3. With every
meeting I was hoping to run the implementation through use cases of various
interesting parties and narrow down the scope of the huge fuzzy beast that CDF
was. With every meeting the scope actually broadened, with no clear path at
sight anywhere.

Earlier this year I was about to drop one of the requirements on which I had
based CDF v2: sharing drivers between DRM/KMS and V4L2. With only two HDMI
transmitters as use cases for that feature (with only out-of-tree drivers so
far), I just thought the involved completely wasn't worth it and that I should
implement CDF v3 as a DRM/KMS-only helper framework. However, a seemingly
unrelated discussion with Xilinx developers showed me that hybrid SoC-FPGA
platforms such as the Xilinx Zynq 7000 have a larger library of IP cores that
can be used in camera capture pipelines and in display pipelines. The two use
cases suddenly became tens or even hundreds of use cases that I couldn't
ignore anymore.

CDF v3 is thus userspace API agnostic. It isn't tied to DRM/KMS or V4L2 and
can be used by any kernel subsystem, potentially including FBDEV (although I
won't personally wrote FBDEV support code, as I've already advocated for FBDEV
to be deprecated).

The code you are about to read is based on the concept of display entities
introduced in v2. Diagrams related to the explanations below are available at
http://ideasonboard.org/media/cdf/20130709-lce-cdf.pdf.


Display Entities
----------------

A display entity abstracts any hardware block that sources, processes or sinks
display-related video streams. It offers an abstract API, implemented by display
entity drivers, that is used by master drivers (such as the main display driver)
to query, configure and control display pipelines.

Display entities are connected to at least one video data bus, and optionally
to a control bus. The video data busses carry display-related video data out
of sources (such as a CRTC in a display controller) to sinks (such as a panel
or a monitor), optionally going through transmitters, encoders, decoders,
bridges or other similar devices. A CRTC or a panel will usually be connected
to a single data bus, while an encoder or a transmitter will be connected to
two data busses.

The simple linear display pipelines we find in most embedded platforms at the
moment are expected to grow more complex with time. CDF needs to accomodate
those needs from the start to be, if not future-proof, at least present-proof
at the time it will get merged in to mainline. For this reason display
entities have data ports through which video streams flow in or out, with link
objects representing the connections between those ports. A typical entity in
a linear display pipeline will have one (for video source and video sink
entities such as CRTCs or panels) or two ports (for video processing entities
such as encoders), but more ports are allowed, and entities can be linked in
complex non-linear pipelines.

Readers might think that this model if extremely similar to the media
controller graph model. They would be right, and given my background this is
most probably not a coincidence. The CDF v3 implementation uses the in-kernel
media controller framework to model the graph of display entities, with the
display entity data structure inheriting from the media entity structure. The
display pipeline graph topology will be automatically exposed to userspace
through the media controller API as an added bonus. However, ussage of the
media controller userspace API in applications is *not* mandatory, and the
current CDF implementation doesn't use the media controller link setup
userspace API to configure the display pipelines.

While some display entities don't require any configuration (DPI panels are a
good example), many of them are connected to a control bus accessible to the
CPU. Control requests can be sent on a dedicated control bus (such as I2C or
SPI) or multiplexed on a mixed control and data bus (such as DBI or DSI). To
support both options the CDF display entity model separates the control and
data busses in different APIs.

Display entities are abstract object that must be implemented by a real
device. The device sits on its control bus and is registered with the Linux
device core and matched with his driver using the control bus specific API.
The CDF doesn't create a display entity class or bus, display entity drivers
thus standard Linux kernel drivers using existing busses. A DBI bus is added
as part of this patch set, but strictly speaking this isn't part of CDF.

When a display entity driver probes a device it must create an instance of the
display_entity structure, initialize it and add it to the CDF core entities
pool. The display entity exposes abstract operations through function
pointers, and the entity driver must implement those operations. Those
operations can act on either the whole entity or on a given port, depending on
the operation. They are divided in two groups, control operations and video
operations.


Control Operations
------------------

Control operations are called by upper-level drivers, usually in response to a
request originating from userspace. They query or control the display entity
state and operation. Currently defined control operations are

- get_size(), to retrieve the entity physical size (applicable to panels only)
- get_modes(), to retrieve the video modes supported at an entity port
- get_params(), to retrieve the data bus parameters at an entity port

- set_state(), to control the state of the entity (off, standby or on)
- update(), to trigger a display update (for entities that implement manual
  update, such as manual-update panels that store frames in their internal
  frame buffer)

The last two operations have been carried from v2 and will be reworked.


Pipeline Control
----------------

The figure on page 4 shows the control model for a linear pipeline. This
differs significantly from CDF v2 where calls where forwarded from entity to
entity using a Russian dolls model. v3 removes the need of neighbour awareness
from entity drivers, simplifying the entity drivers. The complexity of pipeline
configuration is moved to a central location called a pipeline controller
instead of being spread out to all drivers.

Pipeline controllers provide library functions that display drivers can use to
control a pipeline. Several controllers can be implemented to accomodate the
needs of various pipeline topologies and complexities, and display drivers can
even implement their own pipeline control algorithm if needed. I'm working on a
linear pipeline controller for the next version of the patch set.

If pipeline controllers are responsible for propagating a pipeline configuration
on all entity ports in the pipeline, entity drivers are responsible for
propagating the configuration inside entities, from sink (input) to source
(output) ports as illustrated on page 5. The rationale behind this is that
knowledge of the entity internals is located in the entity driver, while
knowledge of the pipeline belongs to the pipeline controller. The controller
will thus configure the pipeline by performing the following steps:

- applying a configuration on sink ports of an entity
- read the configuration that has been propagated by the entity driver on its
  source ports
- optionally, modify the source port configuration (to configure custom timings,
  scaling or other parameters, if supported by the entity)
- propagate the source port configuration to the sink ports of the next entities
  in the pipeline and start over

Beside modifying the active configuration, the entities API will allow trying
configurations without applying them to the hardware. As configuration of a port
possibly depend on the configurations of the other ports, trying a configuration
must be done at the entity level instead of the port level. The implementation
will be based on the concept of configuration store objects that will store the
configuration of all ports for a given entity. Each entity will have a single
active configuration store, and test configuration stores will be created
dynamically to try a configuration on an entity. The get and set operations
implemented by the entity will receive a configuration store pointer, and active
and test code paths in entity drivers will be identical, except for applying the
configuration to the hardware for the active code path.


Video Operations
----------------

Video operations control the video stream state on entity ports. The only
currently defined video operation is

- set_stream(), to start (in continuous or single-shot mode) the video stream
  on an entity port

The call model for video operations differ from the control operations model
described above. The set_stream() operation is called directly by downstream
entities on upstream entities (from a video data bus point of view).
Terminating entities in a pipeline (such as panels) will usually call the
set_stream() operation in their set_state() handler, and intermediate entities
will forward the set_stream() call upstream.


Integration
-----------

The figure on page 8 describes how a panel driver, implemented using CDF as a
display entity, interacts with the other components in the system. The use case
is a simple pipeline made of a display controller and a panel.

The display controller driver receives control request from userspace through
DRM (or FBDEV) API calls. It processes the request and calls the panel driver
through the CDF control operations API. The panel driver will then issue
requests on its control bus (several possible control busses are shown on the
figure, panel drivers typically use one of them only) and call video operations
of the display controller on its left side to control the video stream.


Registration and Notification
-----------------------------

Due to possibly complex dependencies between entities we can't guarantee that
all entities part of the display pipeline will have been successfully probed
when the master display controller driver is probed. For instance a panel can
be a child of the DBI or DSI bus controlled by the display device, or use a
clock provided by that device. We can't defer the display device probe until
the panel is probed and also defer the panel device probe until the display
device is probed. For this reason we need a notification system that allows
entities to register themselves with the CDF core, and display controller
drivers to get notified when entities they need are available.

The notification system has been completely redesigned in v3. This version is
based on the V4L2 asynchronous probing notification code, with large parts of
the code shamelessly copied. This is an interim solution to let me play with
the notification code as needed by CDF. I'm not a fan of code duplication, and
will work on merging the CDF and V4L2 implementations in a later stage when
CDF will reach a mature enough state.

CDF manages a pool of entities and a list of notifiers. Notifiers are
registered by master display drivers with an array of entities match
descriptors. When an entity is added to the CDF entities pool, all notifiers
are searched for a match. If a match is found, the corresponding notifier is
called to notify the master display driver.

The two currently supported match methods are platform match, which uses
device names, and DT match, which uses DT node pointers. More match method
might be added later if needed. Two helper functions exist to build a notifier
from a list of platform device names (in the non-DT case) or a DT
representation of the display pipeline topology.

Once all required entities have been successfully found, the master display
driver is responsible for creating media controller links between all entities
in the pipeline. Two helper functions are also available to automate that
process, one for the non-DT case and one for the DT case. Once again some
DT-related code has been copied from the V4L2 DT code, I will work on merging
both in a future version.

Note that notification brings a different issue after registration, as display
controller and display entity drivers would take a reference to each other.
Those circular references would make driver unloading impossible. One possible
solution to this problem would be to simulate an unplug event for the display
entity, to force the display driver to release the dislay entities it uses. We
would need a userspace API for that though. Better solutions would of course
be welcome.


Device Tree Bindings
--------------------

CDF entities device tree bindings are not documented yet. They describe both
the graph topology and entity-specific information. The graph description uses
the V4L2 DT bindings (which are actually not V4L2-specific) specified at
Documentation/devicetree/bindings/media/video-interfaces.txt. Entity-specific
information will be described in individual DT bindings documentation. The DPI
panel driver uses the display timing bindings documented in
Documentation/devicetree/bindings/video/display-timing.txt.




Please note that most of the display entities on devices I own are just dumb
panels with no control bus, and are thus not the best candidates to design a
framework that needs to take complex panels' needs into account. This is why I
hope to see you using the CDF with your display device and tell me what needs to
be modified/improved/redesigned.

This patch set is split as follows:

- The first patch fixes a Kconfig namespace issue with the OMAP DSS panels. It
  could be applied already independently of this series.
- Patches 02/19 to 07/19 add the CDF core, including the notification system
  and the graph and OF helpers.
- Patch 08/19 adds a MIPI DBI bus. This isn't part of CDF strictly speaking,
  but is needed for the DBI panel drivers.
- Patches 09/19 to 13/19 add panel drivers, a VGA DAC driver and a VGA
  connector driver.
- Patches 14/19 to 18/19 add CDF-compliant reference board code and DT for the
  Renesas Marzen and Lager boards.
- Patch 19/19 port the Renesas R-Car Display Unit driver to CDF.

The patches are available in my git tree at

    git://linuxtv.org/pinchartl/fbdev.git cdf/v3
    http://git.linuxtv.org/pinchartl/fbdev.git/shortlog/refs/heads/cdf/v3

For convenience I've included modifications to the Renesas R-Car Display Unit
driver to use the CDF. You can read the code to see how the driver uses CDF to
interface panels. Please note that the rcar-du-drm implementation is still
work in progress, its set_stream operation implementation doesn't enable and
disable the video stream yet as it should.

As already mentioned in v2, I will appreciate all reviews, comments,
criticisms, ideas, remarks, ... If you can find a clever way to solve the
cyclic references issue described above I'll buy you a beer at the next
conference we will both attend. If you think the proposed solution is too
complex, or too simple, I'm all ears, but I'll have more arguments this time
than I had with v2 :-)

Laurent Pinchart (19):
  OMAPDSS: panels: Rename Kconfig options to OMAP2_DISPLAY_*
  video: Add Common Display Framework core
  video: display: Add video and stream control operations
  video: display: Add display entity notifier
  video: display: Graph helpers
  video: display: OF support
  video: display: Add pixel coding definitions
  video: display: Add MIPI DBI bus support
  video: panel: Add DPI panel support
  video: panel: Add R61505 panel support
  video: panel: Add R61517 panel support
  video: display: Add VGA Digital to Analog Converter support
  video: display: Add VGA connector support
  ARM: shmobile: r8a7790: Add DU clocks for DT
  ARM: shmobile: r8a7790: Add DU device node to device tree
  ARM: shmobile: marzen: Port DU platform data to CDF
  ARM: shmobile: lager: Port DU platform data to CDF
  ARM: shmobile: lager-reference: Add display device nodes to device
    tree
  drm/rcar-du: Port to the Common Display Framework

 arch/arm/boot/dts/r8a7790-lager-reference.dts |  92 ++++
 arch/arm/boot/dts/r8a7790.dtsi                |  33 ++
 arch/arm/mach-shmobile/board-lager.c          |  76 ++-
 arch/arm/mach-shmobile/board-marzen.c         |  77 ++-
 arch/arm/mach-shmobile/clock-r8a7790.c        |   5 +
 drivers/gpu/drm/rcar-du/Kconfig               |   3 +-
 drivers/gpu/drm/rcar-du/Makefile              |   7 +-
 drivers/gpu/drm/rcar-du/rcar_du_connector.c   | 164 ++++++
 drivers/gpu/drm/rcar-du/rcar_du_connector.h   |  36 ++
 drivers/gpu/drm/rcar-du/rcar_du_crtc.h        |   2 +-
 drivers/gpu/drm/rcar-du/rcar_du_drv.c         | 279 ++++++++--
 drivers/gpu/drm/rcar-du/rcar_du_drv.h         |  28 +-
 drivers/gpu/drm/rcar-du/rcar_du_encoder.c     |  87 ++-
 drivers/gpu/drm/rcar-du/rcar_du_encoder.h     |  22 +-
 drivers/gpu/drm/rcar-du/rcar_du_kms.c         | 116 +++-
 drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c     | 131 -----
 drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h     |  25 -
 drivers/gpu/drm/rcar-du/rcar_du_vgacon.c      |  96 ----
 drivers/gpu/drm/rcar-du/rcar_du_vgacon.h      |  23 -
 drivers/video/Kconfig                         |   1 +
 drivers/video/Makefile                        |   1 +
 drivers/video/display/Kconfig                 |  62 +++
 drivers/video/display/Makefile                |   9 +
 drivers/video/display/con-vga.c               | 148 +++++
 drivers/video/display/display-core.c          | 759 ++++++++++++++++++++++++++
 drivers/video/display/display-notifier.c      | 542 ++++++++++++++++++
 drivers/video/display/mipi-dbi-bus.c          | 234 ++++++++
 drivers/video/display/panel-dpi.c             | 207 +++++++
 drivers/video/display/panel-r61505.c          | 567 +++++++++++++++++++
 drivers/video/display/panel-r61517.c          | 460 ++++++++++++++++
 drivers/video/display/vga-dac.c               | 152 ++++++
 drivers/video/omap2/displays-new/Kconfig      |  24 +-
 drivers/video/omap2/displays-new/Makefile     |  24 +-
 include/linux/platform_data/rcar-du.h         |  55 +-
 include/video/display.h                       | 398 ++++++++++++++
 include/video/mipi-dbi-bus.h                  | 125 +++++
 include/video/panel-dpi.h                     |  24 +
 include/video/panel-r61505.h                  |  27 +
 include/video/panel-r61517.h                  |  28 +
 39 files changed, 4615 insertions(+), 534 deletions(-)
 create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_connector.c
 create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_connector.h
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_lvdscon.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/video/display/Kconfig
 create mode 100644 drivers/video/display/Makefile
 create mode 100644 drivers/video/display/con-vga.c
 create mode 100644 drivers/video/display/display-core.c
 create mode 100644 drivers/video/display/display-notifier.c
 create mode 100644 drivers/video/display/mipi-dbi-bus.c
 create mode 100644 drivers/video/display/panel-dpi.c
 create mode 100644 drivers/video/display/panel-r61505.c
 create mode 100644 drivers/video/display/panel-r61517.c
 create mode 100644 drivers/video/display/vga-dac.c
 create mode 100644 include/video/display.h
 create mode 100644 include/video/mipi-dbi-bus.h
 create mode 100644 include/video/panel-dpi.h
 create mode 100644 include/video/panel-r61505.h
 create mode 100644 include/video/panel-r61517.h

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 83+ messages in thread

* [PATCH/RFC v3 01/19] OMAPDSS: panels: Rename Kconfig options to OMAP2_DISPLAY_*
  2013-08-09 17:14 [PATCH/RFC v3 00/19] Common Display Framework Laurent Pinchart
@ 2013-08-09 17:14 ` Laurent Pinchart
  2013-08-09 17:14 ` [PATCH/RFC v3 02/19] video: Add Common Display Framework core Laurent Pinchart
                   ` (20 subsequent siblings)
  21 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2013-08-09 17:14 UTC (permalink / raw)
  To: dri-devel, linux-fbdev, linux-media
  Cc: Sebastien Guiriec, Jesse Barnes, Benjamin Gaignard, Tom Gall,
	Kyungmin Park, Tomi Valkeinen, Stephen Warren, Mark Zhang,
	Stéphane Marchesin, Alexandre Courbot, Ragesh Radhakrishnan,
	Thomas Petazzoni, Sunil Joshi, Maxime Ripard, Vikas Sajjan,
	Marcus Lorentzon

The DISPLAY_ prefix will clash with the Common Display Framework, rename
it.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/video/omap2/displays-new/Kconfig  | 24 ++++++++++++------------
 drivers/video/omap2/displays-new/Makefile | 24 ++++++++++++------------
 2 files changed, 24 insertions(+), 24 deletions(-)

diff --git a/drivers/video/omap2/displays-new/Kconfig b/drivers/video/omap2/displays-new/Kconfig
index 6c90885..2a44b41 100644
--- a/drivers/video/omap2/displays-new/Kconfig
+++ b/drivers/video/omap2/displays-new/Kconfig
@@ -1,68 +1,68 @@
 menu "OMAP Display Device Drivers (new device model)"
         depends on OMAP2_DSS
 
-config DISPLAY_ENCODER_TFP410
+config OMAP2_DISPLAY_ENCODER_TFP410
         tristate "TFP410 DPI to DVI Encoder"
 	help
 	  Driver for TFP410 DPI to DVI encoder.
 
-config DISPLAY_ENCODER_TPD12S015
+config OMAP2_DISPLAY_ENCODER_TPD12S015
         tristate "TPD12S015 HDMI ESD protection and level shifter"
 	help
 	  Driver for TPD12S015, which offers HDMI ESD protection and level
 	  shifting.
 
-config DISPLAY_CONNECTOR_DVI
+config OMAP2_DISPLAY_CONNECTOR_DVI
         tristate "DVI Connector"
 	depends on I2C
 	help
 	  Driver for a generic DVI connector.
 
-config DISPLAY_CONNECTOR_HDMI
+config OMAP2_DISPLAY_CONNECTOR_HDMI
         tristate "HDMI Connector"
 	help
 	  Driver for a generic HDMI connector.
 
-config DISPLAY_CONNECTOR_ANALOG_TV
+config OMAP2_DISPLAY_CONNECTOR_ANALOG_TV
         tristate "Analog TV Connector"
 	help
 	  Driver for a generic analog TV connector.
 
-config DISPLAY_PANEL_DPI
+config OMAP2_DISPLAY_PANEL_DPI
 	tristate "Generic DPI panel"
 	help
 	  Driver for generic DPI panels.
 
-config DISPLAY_PANEL_DSI_CM
+config OMAP2_DISPLAY_PANEL_DSI_CM
 	tristate "Generic DSI Command Mode Panel"
 	help
 	  Driver for generic DSI command mode panels.
 
-config DISPLAY_PANEL_SONY_ACX565AKM
+config OMAP2_DISPLAY_PANEL_SONY_ACX565AKM
 	tristate "ACX565AKM Panel"
 	depends on SPI && BACKLIGHT_CLASS_DEVICE
 	help
 	  This is the LCD panel used on Nokia N900
 
-config DISPLAY_PANEL_LGPHILIPS_LB035Q02
+config OMAP2_DISPLAY_PANEL_LGPHILIPS_LB035Q02
 	tristate "LG.Philips LB035Q02 LCD Panel"
 	depends on SPI
 	help
 	  LCD Panel used on the Gumstix Overo Palo35
 
-config DISPLAY_PANEL_SHARP_LS037V7DW01
+config OMAP2_DISPLAY_PANEL_SHARP_LS037V7DW01
         tristate "Sharp LS037V7DW01 LCD Panel"
         depends on BACKLIGHT_CLASS_DEVICE
         help
           LCD Panel used in TI's SDP3430 and EVM boards
 
-config DISPLAY_PANEL_TPO_TD043MTEA1
+config OMAP2_DISPLAY_PANEL_TPO_TD043MTEA1
         tristate "TPO TD043MTEA1 LCD Panel"
         depends on SPI
         help
           LCD Panel used in OMAP3 Pandora
 
-config DISPLAY_PANEL_NEC_NL8048HL11
+config OMAP2_DISPLAY_PANEL_NEC_NL8048HL11
 	tristate "NEC NL8048HL11 Panel"
 	depends on SPI
 	depends on BACKLIGHT_CLASS_DEVICE
diff --git a/drivers/video/omap2/displays-new/Makefile b/drivers/video/omap2/displays-new/Makefile
index 5aeb11b..768ad94 100644
--- a/drivers/video/omap2/displays-new/Makefile
+++ b/drivers/video/omap2/displays-new/Makefile
@@ -1,12 +1,12 @@
-obj-$(CONFIG_DISPLAY_ENCODER_TFP410) += encoder-tfp410.o
-obj-$(CONFIG_DISPLAY_ENCODER_TPD12S015) += encoder-tpd12s015.o
-obj-$(CONFIG_DISPLAY_CONNECTOR_DVI) += connector-dvi.o
-obj-$(CONFIG_DISPLAY_CONNECTOR_HDMI) += connector-hdmi.o
-obj-$(CONFIG_DISPLAY_CONNECTOR_ANALOG_TV) += connector-analog-tv.o
-obj-$(CONFIG_DISPLAY_PANEL_DPI) += panel-dpi.o
-obj-$(CONFIG_DISPLAY_PANEL_DSI_CM) += panel-dsi-cm.o
-obj-$(CONFIG_DISPLAY_PANEL_SONY_ACX565AKM) += panel-sony-acx565akm.o
-obj-$(CONFIG_DISPLAY_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o
-obj-$(CONFIG_DISPLAY_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
-obj-$(CONFIG_DISPLAY_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
-obj-$(CONFIG_DISPLAY_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o
+obj-$(CONFIG_OMAP2_DISPLAY_ENCODER_TFP410) += encoder-tfp410.o
+obj-$(CONFIG_OMAP2_DISPLAY_ENCODER_TPD12S015) += encoder-tpd12s015.o
+obj-$(CONFIG_OMAP2_DISPLAY_CONNECTOR_DVI) += connector-dvi.o
+obj-$(CONFIG_OMAP2_DISPLAY_CONNECTOR_HDMI) += connector-hdmi.o
+obj-$(CONFIG_OMAP2_DISPLAY_CONNECTOR_ANALOG_TV) += connector-analog-tv.o
+obj-$(CONFIG_OMAP2_DISPLAY_PANEL_DPI) += panel-dpi.o
+obj-$(CONFIG_OMAP2_DISPLAY_PANEL_DSI_CM) += panel-dsi-cm.o
+obj-$(CONFIG_OMAP2_DISPLAY_PANEL_SONY_ACX565AKM) += panel-sony-acx565akm.o
+obj-$(CONFIG_OMAP2_DISPLAY_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o
+obj-$(CONFIG_OMAP2_DISPLAY_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
+obj-$(CONFIG_OMAP2_DISPLAY_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
+obj-$(CONFIG_OMAP2_DISPLAY_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o
-- 
1.8.1.5

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [PATCH/RFC v3 02/19] video: Add Common Display Framework core
  2013-08-09 17:14 [PATCH/RFC v3 00/19] Common Display Framework Laurent Pinchart
  2013-08-09 17:14 ` [PATCH/RFC v3 01/19] OMAPDSS: panels: Rename Kconfig options to OMAP2_DISPLAY_* Laurent Pinchart
@ 2013-08-09 17:14 ` Laurent Pinchart
  2013-09-02  8:42   ` Tomi Valkeinen
  2013-08-09 17:14 ` [PATCH/RFC v3 03/19] video: display: Add video and stream control operations Laurent Pinchart
                   ` (19 subsequent siblings)
  21 siblings, 1 reply; 83+ messages in thread
From: Laurent Pinchart @ 2013-08-09 17:14 UTC (permalink / raw)
  To: dri-devel, linux-fbdev, linux-media
  Cc: Sebastien Guiriec, Jesse Barnes, Benjamin Gaignard, Tom Gall,
	Kyungmin Park, Tomi Valkeinen, Stephen Warren, Mark Zhang,
	Stéphane Marchesin, Alexandre Courbot, Ragesh Radhakrishnan,
	Thomas Petazzoni, Sunil Joshi, Maxime Ripard, Vikas Sajjan,
	Marcus Lorentzon

The Common Display Framework (CDF) splits display devices in entities
that interact through an abstract API. Each entity is managed by its own
driver independently of the other entities, with the framework
orchestrating interactions.

This commit introduces the CDF core with entity (un)registration and
core control operations support.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/video/Kconfig                |   1 +
 drivers/video/Makefile               |   1 +
 drivers/video/display/Kconfig        |   4 +
 drivers/video/display/Makefile       |   2 +
 drivers/video/display/display-core.c | 236 +++++++++++++++++++++++++++++++++++
 include/video/display.h              |  94 ++++++++++++++
 6 files changed, 338 insertions(+)
 create mode 100644 drivers/video/display/Kconfig
 create mode 100644 drivers/video/display/Makefile
 create mode 100644 drivers/video/display/display-core.c
 create mode 100644 include/video/display.h

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 4cf1e1d..c9ca1d5 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -2477,6 +2477,7 @@ source "drivers/video/omap2/Kconfig"
 source "drivers/video/exynos/Kconfig"
 source "drivers/video/mmp/Kconfig"
 source "drivers/video/backlight/Kconfig"
+source "drivers/video/display/Kconfig"
 
 if VT
 	source "drivers/video/console/Kconfig"
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index e8bae8d..d7fd4a2 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -15,6 +15,7 @@ fb-objs                           := $(fb-y)
 obj-$(CONFIG_VT)		  += console/
 obj-$(CONFIG_LOGO)		  += logo/
 obj-y				  += backlight/
+obj-y				  += display/
 
 obj-$(CONFIG_EXYNOS_VIDEO)     += exynos/
 
diff --git a/drivers/video/display/Kconfig b/drivers/video/display/Kconfig
new file mode 100644
index 0000000..1d533e7
--- /dev/null
+++ b/drivers/video/display/Kconfig
@@ -0,0 +1,4 @@
+menuconfig DISPLAY_CORE
+	tristate "Display Core"
+	---help---
+	  Support common display framework for graphics devices.
diff --git a/drivers/video/display/Makefile b/drivers/video/display/Makefile
new file mode 100644
index 0000000..3054adc
--- /dev/null
+++ b/drivers/video/display/Makefile
@@ -0,0 +1,2 @@
+display-y					:= display-core.o
+obj-$(CONFIG_DISPLAY_CORE)			+= display.o
diff --git a/drivers/video/display/display-core.c b/drivers/video/display/display-core.c
new file mode 100644
index 0000000..82fc58b
--- /dev/null
+++ b/drivers/video/display/display-core.c
@@ -0,0 +1,236 @@
+/*
+ * Display Core
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * 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.
+ */
+
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <media/media-device.h>
+
+#include <video/display.h>
+#include <video/videomode.h>
+
+/* -----------------------------------------------------------------------------
+ * Control operations
+ */
+
+/**
+ * display_entity_get_modes - Get video modes supported by the display entity
+ * @entity: The display entity
+ * @port: The display entity port
+ * @modes: Pointer to an array of modes
+ *
+ * Fill the modes argument with a pointer to an array of video modes. The array
+ * is owned by the display entity.
+ *
+ * Return the number of supported modes on success (including 0 if no mode is
+ * supported) or a negative error code otherwise.
+ */
+int display_entity_get_modes(struct display_entity *entity, unsigned int port,
+			     const struct videomode **modes)
+{
+	if (port >= entity->entity.num_pads)
+		return -EINVAL;
+
+	if (!entity->ops->ctrl || !entity->ops->ctrl->get_modes)
+		return 0;
+
+	return entity->ops->ctrl->get_modes(entity, port, modes);
+}
+EXPORT_SYMBOL_GPL(display_entity_get_modes);
+
+/**
+ * display_entity_get_size - Get display entity physical size
+ * @entity: The display entity
+ * @width: Physical width in millimeters
+ * @height: Physical height in millimeters
+ *
+ * When applicable, for instance for display panels, retrieve the display
+ * physical size in millimeters.
+ *
+ * Return 0 on success or a negative error code otherwise.
+ */
+int display_entity_get_size(struct display_entity *entity,
+			    unsigned int *width, unsigned int *height)
+{
+	if (!entity->ops->ctrl || !entity->ops->ctrl->get_size)
+		return -EOPNOTSUPP;
+
+	return entity->ops->ctrl->get_size(entity, width, height);
+}
+EXPORT_SYMBOL_GPL(display_entity_get_size);
+
+/**
+ * display_entity_get_params - Get display entity interface parameters
+ * @entity: The display entity
+ * @port: The display entity port
+ * @params: Pointer to interface parameters
+ *
+ * Fill the parameters structure pointed to by the params argument with display
+ * entity interface parameters.
+ *
+ * Return 0 on success or a negative error code otherwise.
+ */
+int display_entity_get_params(struct display_entity *entity, unsigned int port,
+			      struct display_entity_interface_params *params)
+{
+	if (port >= entity->entity.num_pads)
+		return -EINVAL;
+
+	if (!entity->ops->ctrl || !entity->ops->ctrl->get_params)
+		return -EOPNOTSUPP;
+
+	return entity->ops->ctrl->get_params(entity, port, params);
+}
+EXPORT_SYMBOL_GPL(display_entity_get_params);
+
+/* -----------------------------------------------------------------------------
+ * Connections
+ */
+
+/**
+ * display_entity_connect - Connect two entities through a video stream
+ * @source: The video stream source
+ * @sink: The video stream sink
+ *
+ * Set the sink entity source field to the source entity.
+ */
+
+/**
+ * display_entity_disconnect - Disconnect two previously connected entities
+ * @source: The video stream source
+ * @sink: The video stream sink
+ *
+ * Break a connection between two previously connected entities. The source
+ * entity source field is reset to NULL.
+ */
+
+/* -----------------------------------------------------------------------------
+ * Initialization and Cleanup
+ */
+
+static void display_entity_release(struct kref *ref)
+{
+	struct display_entity *entity =
+		container_of(ref, struct display_entity, ref);
+
+	if (entity->release)
+		entity->release(entity);
+}
+
+/**
+ * display_entity_get - get a reference to a display entity
+ * @display_entity: the display entity
+ *
+ * Return the display entity pointer.
+ */
+struct display_entity *display_entity_get(struct display_entity *entity)
+{
+	if (entity == NULL)
+		return NULL;
+
+	kref_get(&entity->ref);
+	return entity;
+}
+EXPORT_SYMBOL_GPL(display_entity_get);
+
+/**
+ * display_entity_put - release a reference to a display entity
+ * @entity: the display entity
+ *
+ * Releasing the last reference to a display entity releases the display entity
+ * itself.
+ */
+void display_entity_put(struct display_entity *entity)
+{
+	kref_put(&entity->ref, display_entity_release);
+}
+EXPORT_SYMBOL_GPL(display_entity_put);
+
+/**
+ * display_entity_init - Initialize a display entity
+ * @entity: display entity to be registered
+ * @num_sinks: number of sink ports
+ * @num_sources: number of source ports
+ *
+ * Initialize the display entity with the given number of sink and source ports.
+ *
+ * Return 0 on success or a negative error code otherwise.
+ */
+int display_entity_init(struct display_entity *entity, unsigned int num_sinks,
+			unsigned int num_sources)
+{
+	struct media_entity *ment = &entity->entity;
+	struct media_pad *pads;
+	unsigned int num_pads;
+	unsigned int i;
+	int ret;
+
+	kref_init(&entity->ref);
+
+	num_pads = num_sinks + num_sources;
+	pads = kzalloc(sizeof(*pads) * num_pads, GFP_KERNEL);
+	if (pads == NULL)
+		return -ENOMEM;
+
+	for (i = 0; i < num_sinks; ++i)
+		pads[i].flags = MEDIA_PAD_FL_SINK;
+	for (; i < num_pads; ++i)
+		pads[i].flags = MEDIA_PAD_FL_SOURCE;
+
+	ment->name = entity->name;
+
+	ret = media_entity_init(ment, num_pads, pads, 0);
+	if (ret < 0) {
+		kfree(pads);
+		return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(display_entity_init);
+
+/**
+ * display_entity_cleanup - Clean a display entity up
+ * @entity: display entity to be cleaned up
+ *
+ * Clean the entity up and free all resources allocated by by
+ * display_entity_init().
+ */
+void display_entity_cleanup(struct display_entity *entity)
+{
+	struct media_entity *ment = &entity->entity;
+
+	kfree(ment->pads);
+	media_entity_cleanup(ment);
+
+	display_entity_put(entity);
+}
+EXPORT_SYMBOL_GPL(display_entity_cleanup);
+
+int display_entity_register(struct media_device *mdev,
+			    struct display_entity *entity)
+{
+	return media_device_register_entity(mdev, &entity->entity);
+}
+EXPORT_SYMBOL_GPL(display_entity_register);
+
+void display_entity_unregister(struct display_entity *entity)
+{
+	media_device_unregister_entity(&entity->entity);
+}
+EXPORT_SYMBOL_GPL(display_entity_unregister);
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_DESCRIPTION("Display Core");
+MODULE_LICENSE("GPL");
diff --git a/include/video/display.h b/include/video/display.h
new file mode 100644
index 0000000..74b227d
--- /dev/null
+++ b/include/video/display.h
@@ -0,0 +1,94 @@
+/*
+ * Display Core
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * 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.
+ */
+
+#ifndef __DISPLAY_H__
+#define __DISPLAY_H__
+
+#include <linux/kref.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <media/media-entity.h>
+
+/* -----------------------------------------------------------------------------
+ * Display Entity
+ */
+
+struct display_entity;
+struct videomode;
+
+enum display_entity_interface_type {
+	DISPLAY_ENTITY_INTERFACE_DPI,
+	DISPLAY_ENTITY_INTERFACE_DBI,
+	DISPLAY_ENTITY_INTERFACE_LVDS,
+	DISPLAY_ENTITY_INTERFACE_VGA,
+};
+
+struct display_entity_interface_params {
+	enum display_entity_interface_type type;
+};
+
+struct display_entity_control_ops {
+	int (*get_size)(struct display_entity *ent,
+			unsigned int *width, unsigned int *height);
+
+	/* Port operations */
+	int (*get_modes)(struct display_entity *entity, unsigned int port,
+			 const struct videomode **modes);
+	int (*get_params)(struct display_entity *entity, unsigned int port,
+			  struct display_entity_interface_params *params);
+};
+
+struct display_entity_ops {
+	const struct display_entity_control_ops *ctrl;
+};
+
+struct display_entity {
+	struct list_head list;
+	struct device *dev;
+	struct module *owner;
+	struct kref ref;
+
+	char name[32];
+	struct media_entity entity;
+
+	const struct display_entity_ops *ops;
+
+	void(*release)(struct display_entity *ent);
+};
+
+static inline struct display_entity *
+to_display_entity(struct media_entity *entity)
+{
+	return container_of(entity, struct display_entity, entity);
+}
+
+int __must_check display_entity_init(struct display_entity *entity,
+				     unsigned int num_sinks,
+				     unsigned int num_sources);
+void display_entity_cleanup(struct display_entity *entity);
+
+int display_entity_register(struct media_device *mdev,
+			    struct display_entity *entity);
+void display_entity_unregister(struct display_entity *entity);
+
+/* Operations */
+struct display_entity *display_entity_get(struct display_entity *entity);
+void display_entity_put(struct display_entity *entity);
+
+int display_entity_get_size(struct display_entity *entity,
+			    unsigned int *width, unsigned int *height);
+int display_entity_get_modes(struct display_entity *entity, unsigned int port,
+			     const struct videomode **modes);
+int display_entity_get_params(struct display_entity *entity, unsigned int port,
+			      struct display_entity_interface_params *params);
+
+#endif /* __DISPLAY_H__ */
-- 
1.8.1.5

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [PATCH/RFC v3 03/19] video: display: Add video and stream control operations
  2013-08-09 17:14 [PATCH/RFC v3 00/19] Common Display Framework Laurent Pinchart
  2013-08-09 17:14 ` [PATCH/RFC v3 01/19] OMAPDSS: panels: Rename Kconfig options to OMAP2_DISPLAY_* Laurent Pinchart
  2013-08-09 17:14 ` [PATCH/RFC v3 02/19] video: Add Common Display Framework core Laurent Pinchart
@ 2013-08-09 17:14 ` Laurent Pinchart
  2013-08-09 17:14 ` [PATCH/RFC v3 04/19] video: display: Add display entity notifier Laurent Pinchart
                   ` (18 subsequent siblings)
  21 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2013-08-09 17:14 UTC (permalink / raw)
  To: dri-devel, linux-fbdev, linux-media
  Cc: Sebastien Guiriec, Jesse Barnes, Benjamin Gaignard, Tom Gall,
	Kyungmin Park, Tomi Valkeinen, Stephen Warren, Mark Zhang,
	Stéphane Marchesin, Alexandre Courbot, Ragesh Radhakrishnan,
	Thomas Petazzoni, Sunil Joshi, Maxime Ripard, Vikas Sajjan,
	Marcus Lorentzon

The video and stream control operations handle video stream management,
both from the control point of view (called in response to userspace
requests) and the video stream point of view (called by entities to
control the video stream they receive on their input(s)).

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/video/display/display-core.c | 82 ++++++++++++++++++++++++++++++++++++
 include/video/display.h              | 49 +++++++++++++++++++++
 2 files changed, 131 insertions(+)

diff --git a/drivers/video/display/display-core.c b/drivers/video/display/display-core.c
index 82fc58b..bb18723 100644
--- a/drivers/video/display/display-core.c
+++ b/drivers/video/display/display-core.c
@@ -25,6 +25,57 @@
  */
 
 /**
+ * display_entity_set_state - Set the display entity operation state
+ * @entity: The display entity
+ * @state: Display entity operation state
+ *
+ * See &enum display_entity_state for information regarding the entity states.
+ *
+ * Return 0 on success or a negative error code otherwise.
+ */
+int display_entity_set_state(struct display_entity *entity,
+			     enum display_entity_state state)
+{
+	int ret;
+
+	if (entity->state == state)
+		return 0;
+
+	if (!entity->ops->ctrl || !entity->ops->ctrl->set_state)
+		return 0;
+
+	ret = entity->ops->ctrl->set_state(entity, state);
+	if (ret < 0)
+		return ret;
+
+	entity->state = state;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(display_entity_set_state);
+
+/**
+ * display_entity_update - Update the display
+ * @entity: The display entity
+ *
+ * Make the display entity ready to receive pixel data and start frame transfer.
+ * This operation can only be called if the display entity is in STANDBY or ON
+ * state.
+ *
+ * The display entity will call the upstream entity in the video chain to start
+ * the video stream.
+ *
+ * Return 0 on success or a negative error code otherwise.
+ */
+int display_entity_update(struct display_entity *entity)
+{
+	if (!entity->ops->ctrl || !entity->ops->ctrl->update)
+		return 0;
+
+	return entity->ops->ctrl->update(entity);
+}
+EXPORT_SYMBOL_GPL(display_entity_update);
+
+/**
  * display_entity_get_modes - Get video modes supported by the display entity
  * @entity: The display entity
  * @port: The display entity port
@@ -95,6 +146,36 @@ int display_entity_get_params(struct display_entity *entity, unsigned int port,
 EXPORT_SYMBOL_GPL(display_entity_get_params);
 
 /* -----------------------------------------------------------------------------
+ * Video operations
+ */
+
+/**
+ * display_entity_set_stream - Control the video stream state
+ * @entity: The display entity
+ * @port: The display entity port
+ * @state: Display video stream state
+ *
+ * Control the video stream state at the entity video output.
+ *
+ * See &enum display_entity_stream_state for information regarding the stream
+ * states.
+ *
+ * Return 0 on success or a negative error code otherwise.
+ */
+int display_entity_set_stream(struct display_entity *entity, unsigned int port,
+			      enum display_entity_stream_state state)
+{
+	if (port >= entity->entity.num_pads)
+		return -EINVAL;
+
+	if (!entity->ops->video || !entity->ops->video->set_stream)
+		return 0;
+
+	return entity->ops->video->set_stream(entity, port, state);
+}
+EXPORT_SYMBOL_GPL(display_entity_set_stream);
+
+/* -----------------------------------------------------------------------------
  * Connections
  */
 
@@ -177,6 +258,7 @@ int display_entity_init(struct display_entity *entity, unsigned int num_sinks,
 	int ret;
 
 	kref_init(&entity->ref);
+	entity->state = DISPLAY_ENTITY_STATE_OFF;
 
 	num_pads = num_sinks + num_sources;
 	pads = kzalloc(sizeof(*pads) * num_pads, GFP_KERNEL);
diff --git a/include/video/display.h b/include/video/display.h
index 74b227d..fef05a68 100644
--- a/include/video/display.h
+++ b/include/video/display.h
@@ -25,6 +25,38 @@
 struct display_entity;
 struct videomode;
 
+/**
+ * enum display_entity_state - State of a display entity
+ * @DISPLAY_ENTITY_STATE_OFF: The entity is turned off completely, possibly
+ *	including its power supplies. Communication with a display entity in
+ *	that state is not possible.
+ * @DISPLAY_ENTITY_STATE_STANDBY: The entity is in a low-power state. Full
+ *	communication with the display entity is supported, including pixel data
+ *	transfer, but the output is kept blanked.
+ * @DISPLAY_ENTITY_STATE_ON: The entity is fully operational.
+ */
+enum display_entity_state {
+	DISPLAY_ENTITY_STATE_OFF,
+	DISPLAY_ENTITY_STATE_STANDBY,
+	DISPLAY_ENTITY_STATE_ON,
+};
+
+/**
+ * enum display_entity_stream_state - State of a video stream
+ * @DISPLAY_ENTITY_STREAM_STOPPED: The video stream is stopped, no frames are
+ *	transferred.
+ * @DISPLAY_ENTITY_STREAM_SINGLE_SHOT: The video stream has been started for
+ *      single shot operation. The source entity will transfer a single frame
+ *      and then stop.
+ * @DISPLAY_ENTITY_STREAM_CONTINUOUS: The video stream is running, frames are
+ *	transferred continuously by the source entity.
+ */
+enum display_entity_stream_state {
+	DISPLAY_ENTITY_STREAM_STOPPED,
+	DISPLAY_ENTITY_STREAM_SINGLE_SHOT,
+	DISPLAY_ENTITY_STREAM_CONTINUOUS,
+};
+
 enum display_entity_interface_type {
 	DISPLAY_ENTITY_INTERFACE_DPI,
 	DISPLAY_ENTITY_INTERFACE_DBI,
@@ -39,6 +71,9 @@ struct display_entity_interface_params {
 struct display_entity_control_ops {
 	int (*get_size)(struct display_entity *ent,
 			unsigned int *width, unsigned int *height);
+	int (*set_state)(struct display_entity *ent,
+			 enum display_entity_state state);
+	int (*update)(struct display_entity *ent);
 
 	/* Port operations */
 	int (*get_modes)(struct display_entity *entity, unsigned int port,
@@ -47,8 +82,14 @@ struct display_entity_control_ops {
 			  struct display_entity_interface_params *params);
 };
 
+struct display_entity_video_ops {
+	int (*set_stream)(struct display_entity *ent, unsigned int port,
+			  enum display_entity_stream_state state);
+};
+
 struct display_entity_ops {
 	const struct display_entity_control_ops *ctrl;
+	const struct display_entity_video_ops *video;
 };
 
 struct display_entity {
@@ -63,6 +104,8 @@ struct display_entity {
 	const struct display_entity_ops *ops;
 
 	void(*release)(struct display_entity *ent);
+
+	enum display_entity_state state;
 };
 
 static inline struct display_entity *
@@ -86,9 +129,15 @@ void display_entity_put(struct display_entity *entity);
 
 int display_entity_get_size(struct display_entity *entity,
 			    unsigned int *width, unsigned int *height);
+int display_entity_set_state(struct display_entity *entity,
+			     enum display_entity_state state);
+int display_entity_update(struct display_entity *entity);
 int display_entity_get_modes(struct display_entity *entity, unsigned int port,
 			     const struct videomode **modes);
 int display_entity_get_params(struct display_entity *entity, unsigned int port,
 			      struct display_entity_interface_params *params);
 
+int display_entity_set_stream(struct display_entity *entity, unsigned int port,
+			      enum display_entity_stream_state state);
+
 #endif /* __DISPLAY_H__ */
-- 
1.8.1.5

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [PATCH/RFC v3 04/19] video: display: Add display entity notifier
  2013-08-09 17:14 [PATCH/RFC v3 00/19] Common Display Framework Laurent Pinchart
                   ` (2 preceding siblings ...)
  2013-08-09 17:14 ` [PATCH/RFC v3 03/19] video: display: Add video and stream control operations Laurent Pinchart
@ 2013-08-09 17:14 ` Laurent Pinchart
  2013-08-09 17:14 ` [PATCH/RFC v3 05/19] video: display: Graph helpers Laurent Pinchart
                   ` (17 subsequent siblings)
  21 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2013-08-09 17:14 UTC (permalink / raw)
  To: dri-devel, linux-fbdev, linux-media
  Cc: Sebastien Guiriec, Jesse Barnes, Benjamin Gaignard, Tom Gall,
	Kyungmin Park, Tomi Valkeinen, Stephen Warren, Mark Zhang,
	Stéphane Marchesin, Alexandre Courbot, Ragesh Radhakrishnan,
	Thomas Petazzoni, Sunil Joshi, Maxime Ripard, Vikas Sajjan,
	Marcus Lorentzon

Display entities are initialized by they respective drivers
asynchronously with the master display driver. The notifier
infrastructure allows display drivers to create a list of entities they
need (based on platform data) and be notified when those entities are
added to or removed from the system.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/video/display/Makefile           |   3 +-
 drivers/video/display/display-notifier.c | 304 +++++++++++++++++++++++++++++++
 include/video/display.h                  |  66 +++++++
 3 files changed, 372 insertions(+), 1 deletion(-)
 create mode 100644 drivers/video/display/display-notifier.c

diff --git a/drivers/video/display/Makefile b/drivers/video/display/Makefile
index 3054adc..b907aad 100644
--- a/drivers/video/display/Makefile
+++ b/drivers/video/display/Makefile
@@ -1,2 +1,3 @@
-display-y					:= display-core.o
+display-y					:= display-core.o \
+						   display-notifier.o
 obj-$(CONFIG_DISPLAY_CORE)			+= display.o
diff --git a/drivers/video/display/display-notifier.c b/drivers/video/display/display-notifier.c
new file mode 100644
index 0000000..c9210ec
--- /dev/null
+++ b/drivers/video/display/display-notifier.c
@@ -0,0 +1,304 @@
+/*
+ * Display Notifier
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * 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.
+ */
+
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+
+#include <video/display.h>
+
+static LIST_HEAD(display_entity_list);
+static LIST_HEAD(display_entity_notifiers);
+static DEFINE_MUTEX(display_entity_mutex);
+
+/* -----------------------------------------------------------------------------
+ * Notifiers
+ */
+
+static bool match_platform(struct device *dev,
+			   struct display_entity_match *match)
+{
+	pr_debug("%s: matching device '%s' with name '%s'\n", __func__,
+		 dev_name(dev), match->match.platform.name);
+
+	return !strcmp(match->match.platform.name, dev_name(dev));
+}
+
+static struct display_entity_match *
+display_entity_notifier_match(struct display_entity_notifier *notifier,
+			      struct display_entity *entity)
+{
+	bool (*match_func)(struct device *, struct display_entity_match *);
+	struct display_entity_match *match;
+
+	pr_debug("%s: matching entity '%s' (ptr 0x%p dev '%s')\n", __func__,
+		 entity->name, entity, dev_name(entity->dev));
+
+	list_for_each_entry(match, &notifier->waiting, list) {
+		switch (match->type) {
+		default:
+		case DISPLAY_ENTITY_BUS_PLATFORM:
+			match_func = match_platform;
+			break;
+		}
+
+		if (match_func(entity->dev, match))
+			return match;
+	}
+
+	return NULL;
+}
+
+static void display_entity_notifier_cleanup(struct display_entity *entity)
+{
+	entity->match = NULL;
+	entity->notifier = NULL;
+}
+
+static int
+display_entity_notifier_notify(struct display_entity_notifier *notifier,
+			       struct display_entity *entity,
+			       struct display_entity_match *match)
+{
+	int ret;
+
+	pr_debug("%s: notifying device '%s' for entity '%s' (ptr 0x%p dev '%s')\n",
+		 __func__, dev_name(notifier->dev), entity->name, entity,
+		 dev_name(entity->dev));
+
+	/* Remove the match from waiting list. */
+	list_del(&match->list);
+	entity->match = match;
+	entity->notifier = notifier;
+
+	if (notifier->bound) {
+		ret = notifier->bound(notifier, entity, match);
+		if (ret < 0)
+			goto error_bound;
+	}
+
+	/* Move the entity from the global list to the notifier's done list. */
+	list_move(&entity->list, &notifier->done);
+
+	if (list_empty(&notifier->waiting) && notifier->complete) {
+		pr_debug("%s: notifying device '%s' of completion\n", __func__,
+			 dev_name(notifier->dev));
+		ret = notifier->complete(notifier);
+		if (ret < 0)
+			goto error_complete;
+	}
+
+	return 0;
+
+error_complete:
+	/* Move the entity back to the global list. */
+	list_move(&entity->list, &display_entity_list);
+	if (notifier->unbind)
+		notifier->unbind(notifier, entity, match);
+error_bound:
+	/* Put the match back to the waiting list. */
+	list_add_tail(&match->list, &notifier->waiting);
+	display_entity_notifier_cleanup(entity);
+
+	return ret;
+}
+
+/**
+ * display_entity_register_notifier - register a display entity notifier
+ * @notifier: display entity notifier structure we want to register
+ *
+ * Display entity notifiers are called to notify drivers of display
+ * entity-related events for matching display_entitys.
+ *
+ * Notifiers and display_entitys are matched through the device they correspond
+ * to. If the notifier dev field is equal to the display entity dev field the
+ * notifier will be called when an event is reported. Notifiers with a NULL dev
+ * field act as catch-all and will be called for all display_entitys.
+ *
+ * Supported events are
+ *
+ * - DISPLAY_ENTITY_NOTIFIER_CONNECT reports display entity connection and is
+ *   sent at display entity or notifier registration time
+ * - DISPLAY_ENTITY_NOTIFIER_DISCONNECT reports display entity disconnection and
+ *   is sent at display entity unregistration time
+ *
+ * Registering a notifier sends DISPLAY_ENTITY_NOTIFIER_CONNECT events for all
+ * previously registered display_entitys that match the notifiers.
+ *
+ * Return 0 on success.
+ */
+int display_entity_register_notifier(struct display_entity_notifier *notifier)
+{
+	struct display_entity_match *match;
+	struct display_entity *entity;
+	struct display_entity *next;
+	unsigned int i;
+	int ret = 0;
+
+	if (notifier->num_entities == 0)
+		return -EINVAL;
+
+	INIT_LIST_HEAD(&notifier->waiting);
+	INIT_LIST_HEAD(&notifier->done);
+
+	for (i = 0; i < notifier->num_entities; i++) {
+		match = &notifier->entities[i];
+
+		switch (match->type) {
+		case DISPLAY_ENTITY_BUS_PLATFORM:
+			break;
+		default:
+			dev_err(notifier->dev,
+				"%s: Invalid bus type %u on %p\n", __func__,
+				match->type, match);
+			return -EINVAL;
+		}
+
+		list_add_tail(&match->list, &notifier->waiting);
+	}
+
+	mutex_lock(&display_entity_mutex);
+
+	list_add_tail(&notifier->list, &display_entity_notifiers);
+
+	list_for_each_entry_safe(entity, next, &display_entity_list, list) {
+		match = display_entity_notifier_match(notifier, entity);
+		if (!match)
+			continue;
+
+		ret = display_entity_notifier_notify(notifier, entity, match);
+		if (ret)
+			break;
+	}
+
+	mutex_unlock(&display_entity_mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(display_entity_register_notifier);
+
+/**
+ * display_entity_unregister_notifier - unregister a display entity notifier
+ * @notifier: display entity notifier to be unregistered
+ *
+ * Unregistration guarantees that the notifier will never be called upon return
+ * of this function.
+ */
+void display_entity_unregister_notifier(struct display_entity_notifier *notifier)
+{
+	struct display_entity *entity;
+	struct display_entity *next;
+
+	if (notifier->num_entities == 0)
+		return;
+
+	mutex_lock(&display_entity_mutex);
+
+	list_del(&notifier->list);
+
+	list_for_each_entry_safe(entity, next, &notifier->done, list) {
+		if (notifier->unbind)
+			notifier->unbind(notifier, entity, entity->match);
+
+		/* Move the entity back to the global list. */
+		display_entity_notifier_cleanup(entity);
+		list_move(&entity->list, &display_entity_list);
+	}
+	mutex_unlock(&display_entity_mutex);
+}
+EXPORT_SYMBOL_GPL(display_entity_unregister_notifier);
+
+/* -----------------------------------------------------------------------------
+ * Entity Registration
+ */
+
+/**
+ * display_entity_add - add a display entity to the list of available entities
+ * @entity: display entity to be added
+ *
+ * Add the display entity to the list of available entities and send the
+ * DISPLAY_ENTITY_NOTIFIER_CONNECT event to all matching registered notifiers.
+ *
+ * Return 0 on success.
+ */
+int display_entity_add(struct display_entity *entity)
+{
+	struct display_entity_notifier *notifier;
+	struct display_entity_match *match = NULL;
+
+	pr_debug("%s: adding entity '%s' (ptr 0x%p dev '%s')\n", __func__,
+		 entity->name, entity, dev_name(entity->dev));
+
+	mutex_lock(&display_entity_mutex);
+
+	/* Add the entity to the global unbound entities list. It will later be
+	 * moved to the notifier done list by display_entity_notifier_notify().
+	 */
+	list_add_tail(&entity->list, &display_entity_list);
+
+	list_for_each_entry(notifier, &display_entity_notifiers, list) {
+		match = display_entity_notifier_match(notifier, entity);
+		if (match)
+			break;
+	}
+
+	if (match) {
+		/* A match has been found, notify the notifier. */
+		display_entity_notifier_notify(notifier, entity, match);
+	}
+
+	mutex_unlock(&display_entity_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(display_entity_add);
+
+/**
+ * display_entity_remove - removea display entity
+ * @entity: display entity to be removed
+ *
+ * Remove the display entity from the list of available entities and send the
+ * DISPLAY_ENTITY_NOTIFIER_DISCONNECT event to all matching registered
+ * notifiers.
+ */
+void display_entity_remove(struct display_entity *entity)
+{
+	struct display_entity_notifier *notifier = entity->notifier;
+	struct display_entity_match *match = entity->match;
+
+	pr_debug("%s: removing entity '%s' (ptr 0x%p dev '%s')\n", __func__,
+		 entity->name, entity, dev_name(entity->dev));
+
+	if (!notifier) {
+		/* Remove the entity from the global list. */
+		list_del(&entity->list);
+		return;
+	}
+
+	mutex_lock(&display_entity_mutex);
+
+	if (notifier->unbind)
+		notifier->unbind(notifier, entity, match);
+
+	/* Remove the entity from the notifier's done list. */
+	display_entity_notifier_cleanup(entity);
+	list_del(&entity->list);
+
+	/* Move the match back to the waiting list. */
+	list_add_tail(&match->list, &notifier->waiting);
+
+	mutex_unlock(&display_entity_mutex);
+}
+EXPORT_SYMBOL_GPL(display_entity_remove);
diff --git a/include/video/display.h b/include/video/display.h
index fef05a68..2063694 100644
--- a/include/video/display.h
+++ b/include/video/display.h
@@ -23,6 +23,8 @@
  */
 
 struct display_entity;
+struct display_entity_match;
+struct display_entity_notify;
 struct videomode;
 
 /**
@@ -101,6 +103,9 @@ struct display_entity {
 	char name[32];
 	struct media_entity entity;
 
+	struct display_entity_match *match;
+	struct display_entity_notifier *notifier;
+
 	const struct display_entity_ops *ops;
 
 	void(*release)(struct display_entity *ent);
@@ -140,4 +145,65 @@ int display_entity_get_params(struct display_entity *entity, unsigned int port,
 int display_entity_set_stream(struct display_entity *entity, unsigned int port,
 			      enum display_entity_stream_state state);
 
+/* -----------------------------------------------------------------------------
+ * Notifier
+ */
+
+enum display_entity_bus_type {
+	DISPLAY_ENTITY_BUS_PLATFORM,
+};
+
+/**
+ * struct display_entity_match - Display entity description
+ * @type: display entity bus type
+ * @match.platform.name: platform device name
+ * @match.dt.node: DT node
+ * @list: link match objects waiting to be matched
+ */
+struct display_entity_match {
+	enum display_entity_bus_type type;
+	union {
+		struct {
+			const char *name;
+		} platform;
+	} match;
+
+	struct list_head list;
+};
+
+/**
+ * display_entity_notifier - display entity notifier
+ * @num_entities: number of display entities
+ * @entities: array of pointers to subdevice descriptors
+ * @waiting: list of struct v4l2_async_subdev, waiting for their drivers
+ * @done: list of struct v4l2_async_subdev_list, already probed
+ * @list: member in a global list of notifiers
+ * @bound: a display entity has been registered
+ * @complete: all display entities have been registered
+ * @unbind: a display entity is being unregistered
+ */
+struct display_entity_notifier {
+	struct device *dev;
+
+	unsigned int num_entities;
+	struct display_entity_match *entities;
+	struct list_head waiting;
+	struct list_head done;
+	struct list_head list;
+
+	int (*bound)(struct display_entity_notifier *notifier,
+		     struct display_entity *entity,
+		     struct display_entity_match *match);
+	int (*complete)(struct display_entity_notifier *notifier);
+	void (*unbind)(struct display_entity_notifier *notifier,
+		       struct display_entity *entity,
+		       struct display_entity_match *match);
+};
+
+int display_entity_register_notifier(struct display_entity_notifier *notifier);
+void display_entity_unregister_notifier(struct display_entity_notifier *notifier);
+
+int display_entity_add(struct display_entity *entity);
+void display_entity_remove(struct display_entity *entity);
+
 #endif /* __DISPLAY_H__ */
-- 
1.8.1.5

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [PATCH/RFC v3 05/19] video: display: Graph helpers
  2013-08-09 17:14 [PATCH/RFC v3 00/19] Common Display Framework Laurent Pinchart
                   ` (3 preceding siblings ...)
  2013-08-09 17:14 ` [PATCH/RFC v3 04/19] video: display: Add display entity notifier Laurent Pinchart
@ 2013-08-09 17:14 ` Laurent Pinchart
  2013-08-09 17:14 ` [PATCH/RFC v3 06/19] video: display: OF support Laurent Pinchart
                   ` (16 subsequent siblings)
  21 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2013-08-09 17:14 UTC (permalink / raw)
  To: dri-devel, linux-fbdev, linux-media
  Cc: Sebastien Guiriec, Jesse Barnes, Benjamin Gaignard, Tom Gall,
	Kyungmin Park, Tomi Valkeinen, Stephen Warren, Mark Zhang,
	Stéphane Marchesin, Alexandre Courbot, Ragesh Radhakrishnan,
	Thomas Petazzoni, Sunil Joshi, Maxime Ripard, Vikas Sajjan,
	Marcus Lorentzon

Add two graph helper functions. display_entity_build_notifier() builds
an entity notifier from an entities graph represented as a flat array,
typically passed from platform data. display_entity_link_graph() can
then be used to create media controller links between all entities in
the graph.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/video/display/display-core.c     | 107 +++++++++++++++++++++++++++++++
 drivers/video/display/display-notifier.c |  51 +++++++++++++++
 include/video/display.h                  |  20 ++++++
 3 files changed, 178 insertions(+)

diff --git a/drivers/video/display/display-core.c b/drivers/video/display/display-core.c
index bb18723..c3b47d3 100644
--- a/drivers/video/display/display-core.c
+++ b/drivers/video/display/display-core.c
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/device.h>
 #include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -313,6 +314,112 @@ void display_entity_unregister(struct display_entity *entity)
 }
 EXPORT_SYMBOL_GPL(display_entity_unregister);
 
+/* -----------------------------------------------------------------------------
+ * Graph Helpers
+ */
+
+static int display_entity_link_entity(struct device *dev,
+				      struct display_entity *entity,
+				      struct list_head *entities)
+{
+	const struct display_entity_graph_data *graph = entity->match->data;
+	u32 link_flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED;
+	struct media_entity *local = &entity->entity;
+	unsigned int i;
+	int ret = 0;
+
+	dev_dbg(dev, "creating links for entity %s\n", local->name);
+
+	for (i = 0; i < entity->entity.num_pads; ++i) {
+		const struct display_entity_source_data *source;
+		struct media_pad *local_pad = &local->pads[i];
+		struct media_entity *remote = NULL;
+		struct media_pad *remote_pad;
+		struct display_entity *ent;
+
+		dev_dbg(dev, "processing pad %u\n", i);
+
+		/* Skip source pads, they will be processed from the other end
+		 * of the link.
+		 */
+		if (local_pad->flags & MEDIA_PAD_FL_SOURCE) {
+			dev_dbg(dev, "skipping source pad %s:%u\n",
+				local->name, i);
+			continue;
+		}
+
+		/* Find the remote entity. If not found, just skip the link as
+		 * it goes out of scope of the entities handled by the notifier.
+		 */
+		source = &graph->sources[i];
+		list_for_each_entry(ent, entities, list) {
+			if (strcmp(source->name, dev_name(ent->dev)) == 0) {
+				remote = &ent->entity;
+				break;
+			}
+		}
+
+		if (remote == NULL) {
+			dev_dbg(dev, "no entity found for %s\n", source->name);
+			continue;
+		}
+
+		if (source->port >= remote->num_pads) {
+			dev_err(dev, "invalid port number %u on %s\n",
+				source->port, source->name);
+			ret = -EINVAL;
+			break;
+		}
+
+		remote_pad = &remote->pads[source->port];
+
+		/* Create the media link. */
+		dev_dbg(dev, "creating %s:%u -> %s:%u link\n",
+			remote->name, remote_pad->index,
+			local->name, local_pad->index);
+
+		ret = media_entity_create_link(remote, remote_pad->index,
+					       local, local_pad->index,
+					       link_flags);
+		if (ret < 0) {
+			dev_err(dev, "failed to create %s:%u -> %s:%u link\n",
+				remote->name, remote_pad->index,
+				local->name, local_pad->index);
+			break;
+		}
+	}
+
+	return ret;
+}
+
+/**
+ * display_entity_link_graph - Link all entities in a graph
+ * @dev: device used to print debugging and error messages
+ * @entities: list of display entities in the graph
+ *
+ * This function creates media controller links for all entities in a graph
+ * based on graph link data. It relies on the entities match data pointers
+ * having been initialized by the display_entity_build_notifier() function when
+ * building the notifier and thus can't be used when the notifier is built in a
+ * different way.
+ *
+ * Return 0 on success or a negative error code otherwise.
+ */
+int display_entity_link_graph(struct device *dev, struct list_head *entities)
+{
+	struct display_entity *entity;
+	int ret;
+
+	list_for_each_entry(entity, entities, list) {
+		ret = display_entity_link_entity(dev, entity, entities);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(display_entity_link_graph);
+
 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
 MODULE_DESCRIPTION("Display Core");
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/display/display-notifier.c b/drivers/video/display/display-notifier.c
index c9210ec..2d752b3 100644
--- a/drivers/video/display/display-notifier.c
+++ b/drivers/video/display/display-notifier.c
@@ -220,6 +220,57 @@ void display_entity_unregister_notifier(struct display_entity_notifier *notifier
 }
 EXPORT_SYMBOL_GPL(display_entity_unregister_notifier);
 
+/**
+ * display_entity_build_notifier - build a notifier from graph data
+ * @notifier: display entity notifier to be built
+ * @graph: graph data
+ *
+ * Before registering a notifier drivers must initialize the notifier's list of
+ * entities. This helper function simplifies building the list of entities for
+ * drivers that use an array of struct display_entity_graph_data to describe the
+ * entities graph.
+ *
+ * The function allocates an array of struct display_entity_match, initialize it
+ * from graph data, and sets the notifier entities and num_entities fields.
+ *
+ * The entities array is allocated using the managed memory allocation API on
+ * the notifier device, which must be initialized before calling this function.
+ *
+ * Return 0 on success or a negative error code on error.
+ */
+int display_entity_build_notifier(struct display_entity_notifier *notifier,
+				  const struct display_entity_graph_data *graph)
+{
+	struct display_entity_match *entities;
+	unsigned int num_entities;
+	unsigned int i;
+
+	for (num_entities = 0; graph[num_entities].name; ++num_entities) {
+	}
+
+	if (num_entities == 0)
+		return -EINVAL;
+
+	entities = devm_kzalloc(notifier->dev, sizeof(*notifier->entities) *
+				num_entities, GFP_KERNEL);
+	if (entities == NULL)
+		return -ENOMEM;
+
+	for (i = 0; i < num_entities; ++i) {
+		struct display_entity_match *match = &entities[i];
+
+		match->type = DISPLAY_ENTITY_BUS_PLATFORM;
+		match->match.platform.name = graph[i].name;
+		match->data = &graph[i];
+	}
+
+	notifier->num_entities = num_entities;
+	notifier->entities = entities;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(display_entity_build_notifier);
+
 /* -----------------------------------------------------------------------------
  * Entity Registration
  */
diff --git a/include/video/display.h b/include/video/display.h
index 2063694..58ff0d1 100644
--- a/include/video/display.h
+++ b/include/video/display.h
@@ -159,6 +159,7 @@ enum display_entity_bus_type {
  * @match.platform.name: platform device name
  * @match.dt.node: DT node
  * @list: link match objects waiting to be matched
+ * @data: driver private data, not touched by the core
  */
 struct display_entity_match {
 	enum display_entity_bus_type type;
@@ -169,6 +170,7 @@ struct display_entity_match {
 	} match;
 
 	struct list_head list;
+	const void *data;
 };
 
 /**
@@ -206,4 +208,22 @@ void display_entity_unregister_notifier(struct display_entity_notifier *notifier
 int display_entity_add(struct display_entity *entity);
 void display_entity_remove(struct display_entity *entity);
 
+/* -----------------------------------------------------------------------------
+ * Graph Helpers
+ */
+
+struct display_entity_source_data {
+	const char *name;
+	unsigned int port;
+};
+
+struct display_entity_graph_data {
+	const char *name;
+	const struct display_entity_source_data *sources;
+};
+
+int display_entity_build_notifier(struct display_entity_notifier *notifier,
+				  const struct display_entity_graph_data *graph);
+int display_entity_link_graph(struct device *dev, struct list_head *entities);
+
 #endif /* __DISPLAY_H__ */
-- 
1.8.1.5

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [PATCH/RFC v3 06/19] video: display: OF support
  2013-08-09 17:14 [PATCH/RFC v3 00/19] Common Display Framework Laurent Pinchart
                   ` (4 preceding siblings ...)
  2013-08-09 17:14 ` [PATCH/RFC v3 05/19] video: display: Graph helpers Laurent Pinchart
@ 2013-08-09 17:14 ` Laurent Pinchart
  2013-08-13 14:37   ` Philipp Zabel
  2013-08-09 17:14 ` [PATCH/RFC v3 07/19] video: display: Add pixel coding definitions Laurent Pinchart
                   ` (15 subsequent siblings)
  21 siblings, 1 reply; 83+ messages in thread
From: Laurent Pinchart @ 2013-08-09 17:14 UTC (permalink / raw)
  To: dri-devel, linux-fbdev, linux-media
  Cc: Sebastien Guiriec, Jesse Barnes, Benjamin Gaignard, Tom Gall,
	Kyungmin Park, Tomi Valkeinen, Stephen Warren, Mark Zhang,
	Stéphane Marchesin, Alexandre Courbot, Ragesh Radhakrishnan,
	Thomas Petazzoni, Sunil Joshi, Maxime Ripard, Vikas Sajjan,
	Marcus Lorentzon

Extend the notifier with DT node matching support, and add helper functions to
build the notifier and link entities based on a graph representation in
DT.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/video/display/display-core.c     | 334 +++++++++++++++++++++++++++++++
 drivers/video/display/display-notifier.c | 187 +++++++++++++++++
 include/video/display.h                  |  45 +++++
 3 files changed, 566 insertions(+)

diff --git a/drivers/video/display/display-core.c b/drivers/video/display/display-core.c
index c3b47d3..328ead7 100644
--- a/drivers/video/display/display-core.c
+++ b/drivers/video/display/display-core.c
@@ -14,6 +14,7 @@
 #include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/slab.h>
 
 #include <media/media-device.h>
@@ -315,6 +316,184 @@ void display_entity_unregister(struct display_entity *entity)
 EXPORT_SYMBOL_GPL(display_entity_unregister);
 
 /* -----------------------------------------------------------------------------
+ * OF Helpers
+ */
+
+#ifdef CONFIG_OF
+
+/**
+ * display_of_get_next_endpoint() - get next endpoint node
+ * @parent: pointer to the parent device node
+ * @prev: previous endpoint node, or NULL to get first
+ *
+ * Return: An 'endpoint' node pointer with refcount incremented. Refcount
+ * of the passed @prev node is not decremented, the caller have to use
+ * of_node_put() on it when done.
+ */
+struct device_node *
+display_of_get_next_endpoint(const struct device_node *parent,
+			     struct device_node *prev)
+{
+	struct device_node *endpoint;
+	struct device_node *port = NULL;
+
+	if (!parent)
+		return NULL;
+
+	if (!prev) {
+		struct device_node *node;
+		/*
+		 * It's the first call, we have to find a port subnode
+		 * within this node or within an optional 'ports' node.
+		 */
+		node = of_get_child_by_name(parent, "ports");
+		if (node)
+			parent = node;
+
+		port = of_get_child_by_name(parent, "port");
+
+		if (port) {
+			/* Found a port, get an endpoint. */
+			endpoint = of_get_next_child(port, NULL);
+			of_node_put(port);
+		} else {
+			endpoint = NULL;
+		}
+
+		if (!endpoint)
+			pr_err("%s(): no endpoint nodes specified for %s\n",
+			       __func__, parent->full_name);
+		of_node_put(node);
+	} else {
+		port = of_get_parent(prev);
+		if (!port)
+			/* Hm, has someone given us the root node ?... */
+			return NULL;
+
+		/* Avoid dropping prev node refcount to 0. */
+		of_node_get(prev);
+		endpoint = of_get_next_child(port, prev);
+		if (endpoint) {
+			of_node_put(port);
+			return endpoint;
+		}
+
+		/* No more endpoints under this port, try the next one. */
+		do {
+			port = of_get_next_child(parent, port);
+			if (!port)
+				return NULL;
+		} while (of_node_cmp(port->name, "port"));
+
+		/* Pick up the first endpoint in this port. */
+		endpoint = of_get_next_child(port, NULL);
+		of_node_put(port);
+	}
+
+	return endpoint;
+}
+
+/**
+ * display_of_get_remote_port_parent() - get remote port's parent node
+ * @node: pointer to a local endpoint device_node
+ *
+ * Return: Remote device node associated with remote endpoint node linked
+ *	   to @node. Use of_node_put() on it when done.
+ */
+struct device_node *
+display_of_get_remote_port_parent(const struct device_node *node)
+{
+	struct device_node *np;
+	unsigned int depth;
+
+	/* Get remote endpoint node. */
+	np = of_parse_phandle(node, "remote-endpoint", 0);
+
+	/* Walk 3 levels up only if there is 'ports' node. */
+	for (depth = 3; depth && np; depth--) {
+		np = of_get_next_parent(np);
+		if (depth == 2 && of_node_cmp(np->name, "ports"))
+			break;
+	}
+	return np;
+}
+
+/**
+ * struct display_of_link - a link between two endpoints
+ * @local_node: pointer to device_node of this endpoint
+ * @local_port: identifier of the port this endpoint belongs to
+ * @remote_node: pointer to device_node of the remote endpoint
+ * @remote_port: identifier of the port the remote endpoint belongs to
+ */
+struct display_of_link {
+	struct device_node *local_node;
+	unsigned int local_port;
+	struct device_node *remote_node;
+	unsigned int remote_port;
+};
+
+/**
+ * display_of_parse_link() - parse a link between two endpoints
+ * @node: pointer to the endpoint at the local end of the link
+ * @link: pointer to the display OF link data structure
+ *
+ * Fill the link structure with the local and remote nodes and port numbers.
+ * The local_node and remote_node fields are set to point to the local and
+ * remote port parent nodes respectively (the port parent node being the parent
+ * node of the port node if that node isn't a 'ports' node, or the grand-parent
+ * node of the port node otherwise).
+ *
+ * A reference is taken to both the local and remote nodes, the caller must use
+ * display_of_put_link() to drop the references when done with the link.
+ *
+ * Return: 0 on success, or -ENOLINK if the remote endpoint can't be found.
+ */
+static int display_of_parse_link(const struct device_node *node,
+				 struct display_of_link *link)
+{
+	struct device_node *np;
+
+	memset(link, 0, sizeof(*link));
+
+	np = of_get_parent(node);
+	of_property_read_u32(np, "reg", &link->local_port);
+	np = of_get_next_parent(np);
+	if (of_node_cmp(np->name, "ports") == 0)
+		np = of_get_next_parent(np);
+	link->local_node = np;
+
+	np = of_parse_phandle(node, "remote-endpoint", 0);
+	if (!np) {
+		of_node_put(link->local_node);
+		return -ENOLINK;
+	}
+
+	np = of_get_parent(np);
+	of_property_read_u32(np, "reg", &link->remote_port);
+	np = of_get_next_parent(np);
+	if (of_node_cmp(np->name, "ports") == 0)
+		np = of_get_next_parent(np);
+	link->remote_node = np;
+
+	return 0;
+}
+
+/**
+ * display_of_put_link() - drop references to nodes in a link
+ * @link: pointer to the display OF link data structure
+ *
+ * Drop references to the local and remote nodes in the link. This function must
+ * be called on every link parsed with display_of_parse_link().
+ */
+static void display_of_put_link(struct display_of_link *link)
+{
+	of_node_put(link->local_node);
+	of_node_put(link->remote_node);
+}
+
+#endif /* CONFIG_OF */
+
+/* -----------------------------------------------------------------------------
  * Graph Helpers
  */
 
@@ -420,6 +599,161 @@ int display_entity_link_graph(struct device *dev, struct list_head *entities)
 }
 EXPORT_SYMBOL_GPL(display_entity_link_graph);
 
+#ifdef CONFIG_OF
+
+static int display_of_entity_link_entity(struct device *dev,
+					 struct display_entity *entity,
+					 struct list_head *entities,
+					 struct display_entity *root)
+{
+	u32 link_flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED;
+	const struct device_node *node = entity->dev->of_node;
+	struct media_entity *local = &entity->entity;
+	struct device_node *ep = NULL;
+	int ret = 0;
+
+	dev_dbg(dev, "creating links for entity %s\n", local->name);
+
+	while (1) {
+		struct media_entity *remote = NULL;
+		struct media_pad *remote_pad;
+		struct media_pad *local_pad;
+		struct display_of_link link;
+		struct display_entity *ent;
+		struct device_node *next;
+
+		/* Get the next endpoint and parse its link. */
+		next = display_of_get_next_endpoint(node, ep);
+		if (next == NULL)
+			break;
+
+		of_node_put(ep);
+		ep = next;
+
+		dev_dbg(dev, "processing endpoint %s\n", ep->full_name);
+
+		ret = display_of_parse_link(ep, &link);
+		if (ret < 0) {
+			dev_err(dev, "failed to parse link for %s\n",
+				ep->full_name);
+			continue;
+		}
+
+		/* Skip source pads, they will be processed from the other end of
+		 * the link.
+		 */
+		if (link.local_port >= local->num_pads) {
+			dev_err(dev, "invalid port number %u on %s\n",
+				link.local_port, link.local_node->full_name);
+			display_of_put_link(&link);
+			ret = -EINVAL;
+			break;
+		}
+
+		local_pad = &local->pads[link.local_port];
+
+		if (local_pad->flags & MEDIA_PAD_FL_SOURCE) {
+			dev_dbg(dev, "skipping source port %s:%u\n",
+				link.local_node->full_name, link.local_port);
+			display_of_put_link(&link);
+			continue;
+		}
+
+		/* Find the remote entity. If not found, just skip the link as
+		 * it goes out of scope of the entities handled by the notifier.
+		 */
+		list_for_each_entry(ent, entities, list) {
+			if (ent->dev->of_node == link.remote_node) {
+				remote = &ent->entity;
+				break;
+			}
+		}
+
+		if (root->dev->of_node == link.remote_node)
+			remote = &root->entity;
+
+		if (remote == NULL) {
+			dev_dbg(dev, "no entity found for %s\n",
+				link.remote_node->full_name);
+			display_of_put_link(&link);
+			continue;
+		}
+
+		if (link.remote_port >= remote->num_pads) {
+			dev_err(dev, "invalid port number %u on %s\n",
+				link.remote_port, link.remote_node->full_name);
+			display_of_put_link(&link);
+			ret = -EINVAL;
+			break;
+		}
+
+		remote_pad = &remote->pads[link.remote_port];
+
+		display_of_put_link(&link);
+
+		/* Create the media link. */
+		dev_dbg(dev, "creating %s:%u -> %s:%u link\n",
+			remote->name, remote_pad->index,
+			local->name, local_pad->index);
+
+		ret = media_entity_create_link(remote, remote_pad->index,
+					       local, local_pad->index,
+					       link_flags);
+		if (ret < 0) {
+			dev_err(dev,
+				"failed to create %s:%u -> %s:%u link\n",
+				remote->name, remote_pad->index,
+				local->name, local_pad->index);
+			break;
+		}
+	}
+
+	of_node_put(ep);
+	return ret;
+}
+
+/**
+ * display_of_entity_link_graph - Link all entities in a graph
+ * @dev: device used to print debugging and error messages
+ * @root: optional root display entity
+ * @entities: list of display entities in the graph
+ *
+ * This function creates media controller links for all entities in a graph
+ * based on the device tree graph representation. It relies on all entities
+ * having been instantiated from the device tree.
+ *
+ * The list of entities is typically taken directly from a display notifier
+ * done list. It will thus not include any display entity not handled by the
+ * notifier, such as entities directly accessible by the caller without going
+ * through the notification process. The optional root entity parameter can be
+ * used to pass such a display entity and include it in the graph. For all
+ * practical purpose the root entity is handled is if it was part of the
+ * entities list.
+ *
+ * Return 0 on success or a negative error code otherwise.
+ */
+int display_of_entity_link_graph(struct device *dev, struct list_head *entities,
+				 struct display_entity *root)
+{
+	struct display_entity *entity;
+	int ret;
+
+	list_for_each_entry(entity, entities, list) {
+		if (WARN_ON(entity->match->type != DISPLAY_ENTITY_BUS_DT))
+			return -EINVAL;
+
+		ret = display_of_entity_link_entity(dev, entity, entities,
+						    root);
+		if (ret < 0)
+			return ret;
+	}
+
+	return display_of_entity_link_entity(dev, root, entities, root);
+}
+EXPORT_SYMBOL_GPL(display_of_entity_link_graph);
+
+#endif
+
 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
 MODULE_DESCRIPTION("Display Core");
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/display/display-notifier.c b/drivers/video/display/display-notifier.c
index 2d752b3..6bede03 100644
--- a/drivers/video/display/display-notifier.c
+++ b/drivers/video/display/display-notifier.c
@@ -16,6 +16,7 @@
 #include <linux/list.h>
 #include <linux/mutex.h>
 #include <linux/of.h>
+#include <linux/slab.h>
 
 #include <video/display.h>
 
@@ -36,6 +37,14 @@ static bool match_platform(struct device *dev,
 	return !strcmp(match->match.platform.name, dev_name(dev));
 }
 
+static bool match_dt(struct device *dev, struct display_entity_match *match)
+{
+	pr_debug("%s: matching device node '%s' with node '%s'\n", __func__,
+		 dev->of_node->full_name, match->match.dt.node->full_name);
+
+	return match->match.dt.node == dev->of_node;
+}
+
 static struct display_entity_match *
 display_entity_notifier_match(struct display_entity_notifier *notifier,
 			      struct display_entity *entity)
@@ -52,6 +61,9 @@ display_entity_notifier_match(struct display_entity_notifier *notifier,
 		case DISPLAY_ENTITY_BUS_PLATFORM:
 			match_func = match_platform;
 			break;
+		case DISPLAY_ENTITY_BUS_DT:
+			match_func = match_dt;
+			break;
 		}
 
 		if (match_func(entity->dev, match))
@@ -158,6 +170,7 @@ int display_entity_register_notifier(struct display_entity_notifier *notifier)
 
 		switch (match->type) {
 		case DISPLAY_ENTITY_BUS_PLATFORM:
+		case DISPLAY_ENTITY_BUS_DT:
 			break;
 		default:
 			dev_err(notifier->dev,
@@ -272,6 +285,180 @@ int display_entity_build_notifier(struct display_entity_notifier *notifier,
 EXPORT_SYMBOL_GPL(display_entity_build_notifier);
 
 /* -----------------------------------------------------------------------------
+ * OF Support
+ */
+
+#ifdef CONFIG_OF
+
+struct display_entity_of {
+	struct list_head list;
+	struct device_node *node;
+};
+
+static struct display_entity_of *
+display_of_find_entity(struct list_head *entities,
+		       const struct device_node *node)
+{
+	struct display_entity_of *entity;
+
+	list_for_each_entry(entity, entities, list) {
+		if (entity->node == node)
+			return entity;
+	}
+
+	return NULL;
+}
+
+static int display_of_parse_dt(struct display_entity_notifier *notifier,
+			       struct list_head *entities,
+			       struct device_node *node)
+{
+	struct display_entity_of *entity;
+	struct device_node *remote;
+	struct device_node *ep = NULL;
+	struct device_node *next;
+	unsigned int num_entities = 0;
+	int ret = 0;
+
+	/* Walk the device tree and build a list of nodes. */
+	dev_dbg(notifier->dev, "parsing node %s\n", node->full_name);
+
+	while (1) {
+		next = display_of_get_next_endpoint(node, ep);
+		if (next == NULL)
+			break;
+
+		of_node_put(ep);
+		ep = next;
+
+		dev_dbg(notifier->dev, "handling endpoint %s\n", ep->full_name);
+
+		remote = display_of_get_remote_port_parent(ep);
+		if (remote == NULL)
+			continue;
+
+		/* Skip entities that we have already processed. */
+		if (display_of_find_entity(entities, remote) || remote == node) {
+			dev_dbg(notifier->dev,
+				"entity %s already in list, skipping\n",
+				remote->full_name);
+			continue;
+		}
+
+		entity = kzalloc(sizeof(*entity), GFP_KERNEL);
+		if (entity == NULL) {
+			of_node_put(remote);
+			ret = -ENOMEM;
+			break;
+		}
+
+		dev_dbg(notifier->dev, "adding remote entity %s to list\n",
+			remote->full_name);
+
+		entity->node = remote;
+		list_add_tail(&entity->list, entities);
+		num_entities++;
+	}
+
+	of_node_put(ep);
+
+	if (ret < 0)
+		return ret;
+
+	return num_entities;
+}
+
+/**
+ * display_of_entity_build_notifier - build a notifier from device tree
+ * @notifier: display entity notifier to be built
+ * @node: device tree node
+ *
+ * Before registering a notifier drivers must initialize the notifier's list of
+ * entities. This helper function simplifies building the list of entities for
+ * drivers that use a device tree representation of the graph.
+ *
+ * The function allocates an array of struct display_entity_match, initialize it
+ * from the device tree, and sets the notifier entities and num_entities fields.
+ *
+ * The entities array is allocated using the managed memory allocation API on
+ * the notifier device, which must be initialized before calling this function.
+ *
+ * Return 0 on success or a negative error code on error.
+ */
+int display_of_entity_build_notifier(struct display_entity_notifier *notifier,
+				     struct device_node *node)
+{
+	struct display_entity_match *matches;
+	struct display_entity_of *entity;
+	struct display_entity_of *next;
+	unsigned int num_entities = 0;
+	LIST_HEAD(entities);
+	unsigned int i;
+	int ret;
+
+	/* Add an initial entity that stores the device tree node pointer to the
+	 * list.
+	 */
+	entity = kzalloc(sizeof(*entity), GFP_KERNEL);
+	if (entity == NULL)
+		return -ENOMEM;
+
+	entity->node = node;
+	list_add_tail(&entity->list, &entities);
+
+	/* Parse all entities in the list. New entities will be added at the
+	 * tail when parsing the device tree and will just be processed by the
+	 * next iterations.
+	 */
+	list_for_each_entry(entity, &entities, list) {
+		ret = display_of_parse_dt(notifier, &entities, entity->node);
+		if (ret < 0)
+			goto error;
+
+		num_entities += ret;
+	}
+
+	/* Allocate the entity matches array and fill it. */
+	matches = devm_kzalloc(notifier->dev, sizeof(*notifier->entities) *
+				num_entities, GFP_KERNEL);
+	if (matches == NULL) {
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	i = 0;
+	list_for_each_entry_safe(entity, next, &entities, list) {
+		struct display_entity_match *match;
+
+		/* Don't add the initial node to the matches array. */
+		if (entity->node != node) {
+			match = &matches[i++];
+			match->type = DISPLAY_ENTITY_BUS_DT;
+			match->match.dt.node = entity->node;
+		}
+
+		list_del(&entity->list);
+		kfree(entity);
+	}
+
+	notifier->num_entities = num_entities;
+	notifier->entities = matches;
+
+	return 0;
+
+error:
+	list_for_each_entry_safe(entity, next, &entities, list) {
+		list_del(&entity->list);
+		kfree(entity);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(display_of_entity_build_notifier);
+
+#endif /* CONFIG_OF */
+
+/* -----------------------------------------------------------------------------
  * Entity Registration
  */
 
diff --git a/include/video/display.h b/include/video/display.h
index 58ff0d1..36ff637 100644
--- a/include/video/display.h
+++ b/include/video/display.h
@@ -22,6 +22,7 @@
  * Display Entity
  */
 
+struct device_node;
 struct display_entity;
 struct display_entity_match;
 struct display_entity_notify;
@@ -145,12 +146,33 @@ int display_entity_get_params(struct display_entity *entity, unsigned int port,
 int display_entity_set_stream(struct display_entity *entity, unsigned int port,
 			      enum display_entity_stream_state state);
 
+#ifdef CONFIG_OF
+struct device_node *
+display_of_get_next_endpoint(const struct device_node *parent,
+			     struct device_node *prev);
+struct device_node *
+display_of_get_remote_port_parent(const struct device_node *node);
+#else
+static inline struct device_node *
+display_of_get_next_endpoint(const struct device_node *parent,
+			     struct device_node *prev)
+{
+	return NULL;
+}
+static inline struct device_node *
+display_of_get_remote_port_parent(const struct device_node *node)
+{
+	return NULL;
+}
+#endif
+
 /* -----------------------------------------------------------------------------
  * Notifier
  */
 
 enum display_entity_bus_type {
 	DISPLAY_ENTITY_BUS_PLATFORM,
+	DISPLAY_ENTITY_BUS_DT,
 };
 
 /**
@@ -167,6 +189,9 @@ struct display_entity_match {
 		struct {
 			const char *name;
 		} platform;
+		struct {
+			const struct device_node *node;
+		} dt;
 	} match;
 
 	struct list_head list;
@@ -226,4 +251,24 @@ int display_entity_build_notifier(struct display_entity_notifier *notifier,
 				  const struct display_entity_graph_data *graph);
 int display_entity_link_graph(struct device *dev, struct list_head *entities);
 
+#ifdef CONFIG_OF
+int display_of_entity_build_notifier(struct display_entity_notifier *notifier,
+				     struct device_node *node);
+int display_of_entity_link_graph(struct device *dev, struct list_head *entities,
+				 struct display_entity *root);
+#else
+static inline int
+display_of_entity_build_notifier(struct display_entity_notifier *notifier,
+				 struct device_node *node)
+{
+	return -ENOSYS;
+}
+static inline int
+display_of_entity_link_graph(struct device *dev,struct list_head *entities,
+			     struct display_entity *root)
+{
+	return -ENOSYS;
+}
+#endif
+
 #endif /* __DISPLAY_H__ */
-- 
1.8.1.5

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [PATCH/RFC v3 07/19] video: display: Add pixel coding definitions
  2013-08-09 17:14 [PATCH/RFC v3 00/19] Common Display Framework Laurent Pinchart
                   ` (5 preceding siblings ...)
  2013-08-09 17:14 ` [PATCH/RFC v3 06/19] video: display: OF support Laurent Pinchart
@ 2013-08-09 17:14 ` Laurent Pinchart
  2013-08-09 17:14 ` [PATCH/RFC v3 08/19] video: display: Add MIPI DBI bus support Laurent Pinchart
                   ` (14 subsequent siblings)
  21 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2013-08-09 17:14 UTC (permalink / raw)
  To: dri-devel, linux-fbdev, linux-media
  Cc: Sebastien Guiriec, Jesse Barnes, Benjamin Gaignard, Tom Gall,
	Kyungmin Park, Tomi Valkeinen, Stephen Warren, Mark Zhang,
	Stéphane Marchesin, Alexandre Courbot, Ragesh Radhakrishnan,
	Thomas Petazzoni, Sunil Joshi, Maxime Ripard, Vikas Sajjan,
	Marcus Lorentzon

Pixel codings describe how pixels are transmitted on a physical bus. The
information can be communicated between drivers to configure devices.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 include/video/display.h | 120 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 120 insertions(+)

diff --git a/include/video/display.h b/include/video/display.h
index 36ff637..ba319d6 100644
--- a/include/video/display.h
+++ b/include/video/display.h
@@ -18,6 +18,126 @@
 #include <linux/module.h>
 #include <media/media-entity.h>
 
+#define DISPLAY_PIXEL_CODING(option, type, from, to, variant) \
+	(((option) << 17) | ((type) << 13) | ((variant) << 10) | \
+	 ((to) << 5) | (from))
+
+#define DISPLAY_PIXEL_CODING_FROM(coding)	((coding) & 0x1f)
+#define DISPLAY_PIXEL_CODING_TO(coding)		(((coding) >> 5) & 0x1f)
+#define DISPLAY_PIXEL_CODING_VARIANT(coding)	(((coding) >> 10) & 7)
+#define DISPLAY_PIXEL_CODING_TYPE(coding)	(((coding) >> 13) & 0xf)
+
+#define DISPLAY_PIXEL_CODING_TYPE_DBI	0
+#define DISPLAY_PIXEL_CODING_TYPE_DPI	1
+
+/* DBI pixel codings. */
+#define DISPLAY_PIXEL_CODING_DBI(from, to, variant) \
+	DISPLAY_PIXEL_CODING_TYPE(DISPLAY_PIXEL_CODING_TYPE_DBI, \
+				  from, to, variant, 0)
+
+/* Standard DBI codings, defined in the DBI specification. */
+/*   17   16   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1    0 */
+/*    -    -    -    -    -    -    -    -    -    - R0,2 R0,1 R0,0 G0,2 G0,1 G0,0 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_8TO8		DISPLAY_PIXEL_CODING_DBI(8, 8, 0)
+/*    -    -    -    -    -    -    -    -    -    - R0,3 R0,2 R0,1 R0,0 G0,3 G0,2 G0,1 G0,0 */
+/*    -    -    -    -    -    -    -    -    -    - B0,3 B0,2 B0,1 B0,0 R1,3 R1,2 R1,1 R1,0 */
+/*    -    -    -    -    -    -    -    -    -    - G1,3 G1,2 G1,1 G1,0 B1,3 B1,2 B1,1 b1,0 */
+#define DISPLAY_PIXEL_CODING_DBI_12TO8		DISPLAY_PIXEL_CODING_DBI(12, 8, 0)
+/*    -    -    -    -    -    -    -    -    -    - R0,4 R0,3 R0,2 R0,1 R0,0 G0,5 G0,4 G0,3 */
+/*    -    -    -    -    -    -    -    -    -    - G0,2 G0,1 G0,0 B0,4 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_16TO8		DISPLAY_PIXEL_CODING_DBI(16, 8, 0)
+/*    -    -    -    -    -    -    -    -    -    - R0,5 R0,4 R0,3 R0,2 R0,1 R0,0    -    - */
+/*    -    -    -    -    -    -    -    -    -    - G0,5 G0,4 G0,3 G0,2 G0,1 G0,0    -    - */
+/*    -    -    -    -    -    -    -    -    -    - B0,5 B0,4 B0,3 B0,2 B0,1 B0,0    -    - */
+#define DISPLAY_PIXEL_CODING_DBI_18TO8		DISPLAY_PIXEL_CODING_DBI(18, 8, 0)
+/*    -    -    -    -    -    -    -    -    -    - R0,7 R0,6 R0,5 R0,4 R0,3 R0,2 R0,1 R0,0 */
+/*    -    -    -    -    -    -    -    -    -    - G0,7 G0,6 G0,5 G0,4 G0,3 G0,2 G0,1 G0,0 */
+/*    -    -    -    -    -    -    -    -    -    - B0,7 B0,6 B0,5 B0,4 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_24TO8		DISPLAY_PIXEL_CODING_DBI(24, 8, 0)
+/*    -    -    -    -    -    -    -    -    - R0,5 R0,4 R0,3 R0,2 R0,1 R0,0 G0,5 G0,4 G0,4 */
+/*    -    -    -    -    -    -    -    -    - G0,2 G0,1 G0,0 B0,5 B0,4 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_18TO9		DISPLAY_PIXEL_CODING_DBI(18, 9, 0)
+/*    -    - R1,2 R1,1 R1,0 G1,2 G1,1 G1,0 B1,1 B1,0 R0,2 R0,1 R0,0 G0,2 G0,1 G0,0 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_8TO16		DISPLAY_PIXEL_CODING_DBI(8, 16, 0)
+/*    -    -    -    -    -    - R0,3 R0,2 R0,1 R0,0 G0,3 G0,2 G0,1 G0,0 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_12TO16		DISPLAY_PIXEL_CODING_DBI(12, 16, 0)
+/*    -    - R0,4 R0,3 R0,2 R0,1 R0,0 G0,5 G0,4 G0,3 G0,2 G0,1 G0,0 B0,4 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_16TO16		DISPLAY_PIXEL_CODING_DBI(16, 16, 0)
+/*    -    - R0,5 R0,4 R0,3 R0,2 R0,1 R0,0    -    - G0,5 G0,4 G0,3 G0,2 G0,1 G0,0    -    - */
+/*    -    - B0,5 B0,4 B0,3 B0,2 B0,1 B0,0    -    - R1,5 R1,4 R1,3 R1,2 R1,1 R1,0    -    - */
+/*    -    - G1,5 G1,4 G1,3 G1,2 G1,1 G1,0    -    - B1,5 B1,4 B1,3 B1,2 B1,1 B1,0    -    - */
+#define DISPLAY_PIXEL_CODING_DBI_18TO16_A	DISPLAY_PIXEL_CODING_DBI(18, 16, 0)
+/*    -    -    -    -    -    -    -    -    -    - R0,5 R0,4 R0,3 R0,2 R0,1 R0,0    -    - */
+/*    -    - G0,5 G0,4 G0,3 G0,2 G0,1 G0,0    -    - B0,5 B0,4 B0,3 B0,2 B0,1 B0,0    -    - */
+#define DISPLAY_PIXEL_CODING_DBI_18TO16_B	DISPLAY_PIXEL_CODING_DBI(18, 16, 1)
+/*    -    - R0,7 R0,6 R0,5 R0,4 R0,3 R0,2 R0,1 R0,0 G0,7 G0,6 G0,5 G0,4 G0,3 G0,2 G0,1 G0,0 */
+/*    -    - B0,7 B0,6 B0,5 B0,4 B0,3 B0,2 B0,1 B0,0 R1,7 R1,6 R1,5 R1,4 R1,3 R1,2 R1,1 R1,0 */
+/*    -    - G1,7 G1,6 G1,5 G1,4 G1,3 G1,2 G1,1 G1,0 B1,7 B1,6 B1,5 B1,4 B1,3 B1,2 B1,1 B1,0 */
+#define DISPLAY_PIXEL_CODING_DBI_24TO16_A	DISPLAY_PIXEL_CODING_DBI(24, 16, 0)
+/*    -    -    -    -    -    -    -    -    -    - R0,7 R0,6 R0,5 R0,4 R0,3 R0,2 R0,1 R0,0 */
+/*    -    - G0,7 G0,6 G0,5 G0,4 G0,3 G0,2 G0,1 G0,0 B0,7 B0,6 B0,5 B0,4 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_24TO16_B	DISPLAY_PIXEL_CODING_DBI(24, 16, 1)
+
+/* Non-standard DBI pixel codings. */
+/*   17   16   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1    0 */
+/*    -    -    -    -    -    -    -    -    -    - R0,5 R0,4 R0,3 R0,2 R0,1 R0,0 G0,5 G0,4 */
+/*    -    -    -    -    -    -    -    -    -    - G0,3 G0,2 G0,1 G0,0 B0,5 B0,4 B0,3 B0,2 */
+/*    -    -    -    -    -    -    -    -    -    -    -    -    -    -    -    - B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_18TO8_B	DISPLAY_PIXEL_CODING_DBI(18, 8, 1)
+/*    -    -    -    -    -    -    -    -    -    -    -    -    -    -    -    - R0,5 R0,4 */
+/*    -    -    -    -    -    -    -    -    -    - R0,3 R0,2 R0,1 R0,0 G0,5 G0,4 G0,3 G0,2 */
+/*    -    -    -    -    -    -    -    -    -    - G0,1 G0,0 B0,5 B0,4 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_18TO8_C	DISPLAY_PIXEL_CODING_DBI(18, 8, 2)
+/*    -    - R0,5 R0,4 R0,3 R0,2 R0,1 R0,0 G0,5 G0,4 G0,3 G0,2 G0,1 G0,0 B0,5 B0,4 B0,3 B0,2 */
+/*    -    - B0,1 B0,0    -    -    -    -    -    -    -    -    -    -    -    -    -    - */
+#define DISPLAY_PIXEL_CODING_DBI_18TO16_C	DISPLAY_PIXEL_CODING_DBI(18, 16, 2)
+/*    -    - R0,5 R0,4    -    -    -    -    -    -    -    -    -    -    -    -    -    - */
+/*    -    - R0,3 R0,2 R0,1 R0,0 G0,5 G0,4 G0,3 G0,2 G0,1 G0,0 B0,5 B0,4 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_18TO16_D	DISPLAY_PIXEL_CODING_DBI(18, 16, 3)
+/*    -    -    -    -    -    - R0,7 R0,6 R0,5 R0,4 R0,3 R0,2 R0,1 R0,0 G0,7 G0,6 G0,5 G0,4 */
+/*    -    -    -    -    -    - G0,3 G0,2 G0,1 G0,0 B0,7 B0,6 B0,5 B0,4 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_24TO12		DISPLAY_PIXEL_CODING_DBI(24, 12, 0)
+/* R0,5 R0,4 R0,3 R0,2 R0,1 R0,0 G0,5 G0,4 G0,3 G0,2 G0,1 G0,0 B0,5 B0,4 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_18TO18		DISPLAY_PIXEL_CODING_DBI(18, 18, 0)
+
+/* DPI pixel codings. */
+#define DISPLAY_PIXEL_CODING_DPI_RGB(from, to, variant) \
+	DISPLAY_PIXEL_CODING_TYPE(DISPLAY_PIXEL_CODING_TYPE_DPI, \
+				  from, to, variant, 0)
+#define DISPLAY_PIXEL_CODING_DPI_YUV(from, to, variant) \
+	DISPLAY_PIXEL_CODING_TYPE(DISPLAY_PIXEL_CODING_TYPE_DPI, \
+				  from, to, variant, 1)
+
+/* Standard DPI codings, defined in the DPI specification. */
+/* 23 22 21 20 19 28 17 16 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0 */
+/*  -  -  -  -  -  -  -  - R4 R3 R2 R1 R0 G5 G4 G3 G2 G1 G0 B4 B3 B2 B1 B0 */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_16TO16	DISPLAY_PIXEL_CODING_DPI_RGB(16, 16, 0)
+/*  -  -  -  -  -  - R5 R4 R3 R2 R1 R0 G5 G4 G3 G2 G1 G0 B5 B4 B3 B2 B1 B0 */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_18TO18	DISPLAY_PIXEL_CODING_DPI_RGB(18, 18, 0)
+/*  -  -  - R4 R3 R2 R1 R0  -  - G5 G4 G3 G2 G1 G0  -  -  - B4 B3 B2 B1 B0 */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_16TO20	DISPLAY_PIXEL_CODING_DPI_RGB(16, 20, 0)
+/*  -  - R4 R3 R2 R1 R0  -  -  - G5 G4 G3 G2 G1 G0  -  - B4 B3 B2 B1 B0  - */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_16TO22	DISPLAY_PIXEL_CODING_DPI_RGB(16, 22, 0)
+/*  -  - R5 R4 R3 R2 R1 R0  -  - G5 G4 G3 G2 G1 G0  -  - B5 B4 B3 B2 B1 B0 */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_18TO22	DISPLAY_PIXEL_CODING_DPI_RGB(18, 22, 0)
+/* R7 R6 R5 R4 R3 R2 R1 R0 G7 G6 G5 G4 G3 G2 G1 G0 B7 B6 B5 B4 B3 B2 B1 B0 */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_24TO24	DISPLAY_PIXEL_CODING_DPI_RGB(24, 24, 0)
+
+/* Non-standard DPI pixel codings. */
+/* 23 22 21 20 19 28 17 16 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0 */
+/*  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - R7 R6 R5 R4 R3 R2 R1 R0 */
+/*  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - G7 G6 G5 G4 G3 G2 G1 G0 */
+/*  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - B7 B6 B5 B4 B3 B2 B1 B0 */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_24TO8	DISPLAY_PIXEL_CODING_DPI_RGB(24, 8, 0)
+/*  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - R5 R4 R3 R2 R1 R0 G5 G4 G3 */
+/*  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - G2 G1 G0 B5 B4 B3 B2 B1 B0 */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_18TO9	DISPLAY_PIXEL_CODING_DPI_RGB(18, 9, 0)
+/*  -  -  -  -  -  -  -  -  -  -  -  - R3 R2 R1 R0 G3 G2 G1 G0 B3 B2 B1 B0 */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_12TO12	DISPLAY_PIXEL_CODING_DPI_RGB(12, 12, 0)
+/*  -  -  -  -  -  -  -  -  -  -  -  - R7 R6 R5 R4 R3 R2 R1 R0 G7 G6 G5 G4 */
+/*  -  -  -  -  -  -  -  -  -  -  -  - G3 G2 G1 G0 B7 B6 B5 B4 B3 B2 B1 B0 */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_24TO12	DISPLAY_PIXEL_CODING_DPI_RGB(24, 12, 0)
+
 /* -----------------------------------------------------------------------------
  * Display Entity
  */
-- 
1.8.1.5

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [PATCH/RFC v3 08/19] video: display: Add MIPI DBI bus support
  2013-08-09 17:14 [PATCH/RFC v3 00/19] Common Display Framework Laurent Pinchart
                   ` (6 preceding siblings ...)
  2013-08-09 17:14 ` [PATCH/RFC v3 07/19] video: display: Add pixel coding definitions Laurent Pinchart
@ 2013-08-09 17:14 ` Laurent Pinchart
  2013-08-14  0:52   ` Rob Clark
                     ` (3 more replies)
  2013-08-09 17:15 ` [PATCH/RFC v3 09/19] video: panel: Add DPI panel support Laurent Pinchart
                   ` (13 subsequent siblings)
  21 siblings, 4 replies; 83+ messages in thread
From: Laurent Pinchart @ 2013-08-09 17:14 UTC (permalink / raw)
  To: dri-devel, linux-fbdev, linux-media
  Cc: Sebastien Guiriec, Jesse Barnes, Benjamin Gaignard, Tom Gall,
	Kyungmin Park, Tomi Valkeinen, Stephen Warren, Mark Zhang,
	Stéphane Marchesin, Alexandre Courbot, Ragesh Radhakrishnan,
	Thomas Petazzoni, Sunil Joshi, Maxime Ripard, Vikas Sajjan,
	Marcus Lorentzon

MIPI DBI is a configurable-width parallel display bus that transmits
commands and data.

Add a new DBI Linux bus type that implements the usual bus
infrastructure (including devices and drivers (un)registration and
matching, and bus configuration and access functions).

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/video/display/Kconfig        |   8 ++
 drivers/video/display/Makefile       |   1 +
 drivers/video/display/mipi-dbi-bus.c | 234 +++++++++++++++++++++++++++++++++++
 include/video/display.h              |   4 +
 include/video/mipi-dbi-bus.h         | 125 +++++++++++++++++++
 5 files changed, 372 insertions(+)
 create mode 100644 drivers/video/display/mipi-dbi-bus.c
 create mode 100644 include/video/mipi-dbi-bus.h

diff --git a/drivers/video/display/Kconfig b/drivers/video/display/Kconfig
index 1d533e7..f7532c1 100644
--- a/drivers/video/display/Kconfig
+++ b/drivers/video/display/Kconfig
@@ -2,3 +2,11 @@ menuconfig DISPLAY_CORE
 	tristate "Display Core"
 	---help---
 	  Support common display framework for graphics devices.
+
+if DISPLAY_CORE
+
+config DISPLAY_MIPI_DBI
+	tristate
+	default n
+
+endif # DISPLAY_CORE
diff --git a/drivers/video/display/Makefile b/drivers/video/display/Makefile
index b907aad..59022d2 100644
--- a/drivers/video/display/Makefile
+++ b/drivers/video/display/Makefile
@@ -1,3 +1,4 @@
 display-y					:= display-core.o \
 						   display-notifier.o
 obj-$(CONFIG_DISPLAY_CORE)			+= display.o
+obj-$(CONFIG_DISPLAY_MIPI_DBI)			+= mipi-dbi-bus.o
diff --git a/drivers/video/display/mipi-dbi-bus.c b/drivers/video/display/mipi-dbi-bus.c
new file mode 100644
index 0000000..791fb4d
--- /dev/null
+++ b/drivers/video/display/mipi-dbi-bus.c
@@ -0,0 +1,234 @@
+/*
+ * MIPI DBI Bus
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * 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.
+ */
+
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+
+#include <video/mipi-dbi-bus.h>
+
+/* -----------------------------------------------------------------------------
+ * Bus operations
+ */
+
+int mipi_dbi_set_data_width(struct mipi_dbi_device *dev, unsigned int width)
+{
+	if (width != 8 && width != 16)
+		return -EINVAL;
+
+	dev->data_width = width;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(mipi_dbi_set_data_width);
+
+int mipi_dbi_write_command(struct mipi_dbi_device *dev, u16 cmd)
+{
+	return dev->bus->ops->write_command(dev->bus, dev, cmd);
+}
+EXPORT_SYMBOL_GPL(mipi_dbi_write_command);
+
+int mipi_dbi_write_data(struct mipi_dbi_device *dev, const u8 *data,
+			size_t len)
+{
+	return dev->bus->ops->write_data(dev->bus, dev, data, len);
+}
+EXPORT_SYMBOL_GPL(mipi_dbi_write_data);
+
+int mipi_dbi_read_data(struct mipi_dbi_device *dev, u8 *data, size_t len)
+{
+	return dev->bus->ops->read_data(dev->bus, dev, data, len);
+}
+EXPORT_SYMBOL_GPL(mipi_dbi_read_data);
+
+/* -----------------------------------------------------------------------------
+ * Bus type
+ */
+
+static const struct mipi_dbi_device_id *
+mipi_dbi_match_id(const struct mipi_dbi_device_id *id,
+		  struct mipi_dbi_device *dev)
+{
+	while (id->name[0]) {
+		if (strcmp(dev->name, id->name) == 0) {
+			dev->id_entry = id;
+			return id;
+		}
+		id++;
+	}
+	return NULL;
+}
+
+static int mipi_dbi_match(struct device *_dev, struct device_driver *_drv)
+{
+	struct mipi_dbi_device *dev = to_mipi_dbi_device(_dev);
+	struct mipi_dbi_driver *drv = to_mipi_dbi_driver(_drv);
+
+	if (drv->id_table)
+		return mipi_dbi_match_id(drv->id_table, dev) != NULL;
+
+	return (strcmp(dev->name, _drv->name) == 0);
+}
+
+static ssize_t modalias_show(struct device *_dev, struct device_attribute *a,
+			     char *buf)
+{
+	struct mipi_dbi_device *dev = to_mipi_dbi_device(_dev);
+	int len = snprintf(buf, PAGE_SIZE, MIPI_DBI_MODULE_PREFIX "%s\n",
+			   dev->name);
+
+	return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
+}
+
+static struct device_attribute mipi_dbi_dev_attrs[] = {
+	__ATTR_RO(modalias),
+	__ATTR_NULL,
+};
+
+static int mipi_dbi_uevent(struct device *_dev, struct kobj_uevent_env *env)
+{
+	struct mipi_dbi_device *dev = to_mipi_dbi_device(_dev);
+
+	add_uevent_var(env, "MODALIAS=%s%s", MIPI_DBI_MODULE_PREFIX,
+		       dev->name);
+	return 0;
+}
+
+static const struct dev_pm_ops mipi_dbi_dev_pm_ops = {
+	.runtime_suspend = pm_generic_runtime_suspend,
+	.runtime_resume = pm_generic_runtime_resume,
+	.suspend = pm_generic_suspend,
+	.resume = pm_generic_resume,
+	.freeze = pm_generic_freeze,
+	.thaw = pm_generic_thaw,
+	.poweroff = pm_generic_poweroff,
+	.restore = pm_generic_restore,
+};
+
+static struct bus_type mipi_dbi_bus_type = {
+	.name		= "mipi-dbi",
+	.dev_attrs	= mipi_dbi_dev_attrs,
+	.match		= mipi_dbi_match,
+	.uevent		= mipi_dbi_uevent,
+	.pm		= &mipi_dbi_dev_pm_ops,
+};
+
+/* -----------------------------------------------------------------------------
+ * Device and driver (un)registration
+ */
+
+/**
+ * mipi_dbi_device_register - register a DBI device
+ * @dev: DBI device we're registering
+ */
+int mipi_dbi_device_register(struct mipi_dbi_device *dev,
+			      struct mipi_dbi_bus *bus)
+{
+	device_initialize(&dev->dev);
+
+	dev->bus = bus;
+	dev->dev.bus = &mipi_dbi_bus_type;
+	dev->dev.parent = bus->dev;
+
+	if (dev->id != -1)
+		dev_set_name(&dev->dev, "%s.%d", dev->name,  dev->id);
+	else
+		dev_set_name(&dev->dev, "%s", dev->name);
+
+	return device_add(&dev->dev);
+}
+EXPORT_SYMBOL_GPL(mipi_dbi_device_register);
+
+/**
+ * mipi_dbi_device_unregister - unregister a DBI device
+ * @dev: DBI device we're unregistering
+ */
+void mipi_dbi_device_unregister(struct mipi_dbi_device *dev)
+{
+	device_del(&dev->dev);
+	put_device(&dev->dev);
+}
+EXPORT_SYMBOL_GPL(mipi_dbi_device_unregister);
+
+static int mipi_dbi_drv_probe(struct device *_dev)
+{
+	struct mipi_dbi_driver *drv = to_mipi_dbi_driver(_dev->driver);
+	struct mipi_dbi_device *dev = to_mipi_dbi_device(_dev);
+
+	return drv->probe(dev);
+}
+
+static int mipi_dbi_drv_remove(struct device *_dev)
+{
+	struct mipi_dbi_driver *drv = to_mipi_dbi_driver(_dev->driver);
+	struct mipi_dbi_device *dev = to_mipi_dbi_device(_dev);
+	int ret;
+
+	ret = drv->remove(dev);
+	if (ret < 0)
+		return ret;
+
+	mipi_dbi_set_drvdata(dev, NULL);
+
+	return 0;
+}
+
+/**
+ * mipi_dbi_driver_register - register a driver for DBI devices
+ * @drv: DBI driver structure
+ */
+int mipi_dbi_driver_register(struct mipi_dbi_driver *drv)
+{
+	drv->driver.bus = &mipi_dbi_bus_type;
+	if (drv->probe)
+		drv->driver.probe = mipi_dbi_drv_probe;
+	if (drv->remove)
+		drv->driver.remove = mipi_dbi_drv_remove;
+
+	return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(mipi_dbi_driver_register);
+
+/**
+ * mipi_dbi_driver_unregister - unregister a driver for DBI devices
+ * @drv: DBI driver structure
+ */
+void mipi_dbi_driver_unregister(struct mipi_dbi_driver *drv)
+{
+	driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL_GPL(mipi_dbi_driver_unregister);
+
+/* -----------------------------------------------------------------------------
+ * Init/exit
+ */
+
+static int __init mipi_dbi_init(void)
+{
+	return bus_register(&mipi_dbi_bus_type);
+}
+
+static void __exit mipi_dbi_exit(void)
+{
+	bus_unregister(&mipi_dbi_bus_type);
+}
+
+module_init(mipi_dbi_init);
+module_exit(mipi_dbi_exit)
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_DESCRIPTION("MIPI DBI Bus");
+MODULE_LICENSE("GPL");
diff --git a/include/video/display.h b/include/video/display.h
index ba319d6..3138401 100644
--- a/include/video/display.h
+++ b/include/video/display.h
@@ -17,6 +17,7 @@
 #include <linux/list.h>
 #include <linux/module.h>
 #include <media/media-entity.h>
+#include <video/mipi-dbi-bus.h>
 
 #define DISPLAY_PIXEL_CODING(option, type, from, to, variant) \
 	(((option) << 17) | ((type) << 13) | ((variant) << 10) | \
@@ -189,6 +190,9 @@ enum display_entity_interface_type {
 
 struct display_entity_interface_params {
 	enum display_entity_interface_type type;
+	union {
+		struct mipi_dbi_interface_params dbi;
+	} p;
 };
 
 struct display_entity_control_ops {
diff --git a/include/video/mipi-dbi-bus.h b/include/video/mipi-dbi-bus.h
new file mode 100644
index 0000000..876b69d
--- /dev/null
+++ b/include/video/mipi-dbi-bus.h
@@ -0,0 +1,125 @@
+/*
+ * MIPI DBI Bus
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * 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.
+ */
+
+#ifndef __MIPI_DBI_BUS_H__
+#define __MIPI_DBI_BUS_H__
+
+#include <linux/device.h>
+
+struct mipi_dbi_bus;
+struct mipi_dbi_device;
+
+struct mipi_dbi_bus_ops {
+	int (*write_command)(struct mipi_dbi_bus *bus,
+			     struct mipi_dbi_device *dev, u16 cmd);
+	int (*write_data)(struct mipi_dbi_bus *bus, struct mipi_dbi_device *dev,
+			  const u8 *data, size_t len);
+	int (*read_data)(struct mipi_dbi_bus *bus, struct mipi_dbi_device *dev,
+			 u8 *data, size_t len);
+};
+
+struct mipi_dbi_bus {
+	struct device *dev;
+	const struct mipi_dbi_bus_ops *ops;
+};
+
+#define MIPI_DBI_MODULE_PREFIX		"mipi-dbi:"
+#define MIPI_DBI_NAME_SIZE		32
+
+struct mipi_dbi_device_id {
+	char name[MIPI_DBI_NAME_SIZE];
+	__kernel_ulong_t driver_data	/* Data private to the driver */
+			__aligned(sizeof(__kernel_ulong_t));
+};
+
+enum mipi_dbi_interface_type {
+	MIPI_DBI_INTERFACE_TYPE_A,
+	MIPI_DBI_INTERFACE_TYPE_B,
+};
+
+#define MIPI_DBI_INTERFACE_TE		(1 << 0)
+
+struct mipi_dbi_interface_params {
+	enum mipi_dbi_interface_type type;
+	unsigned int flags;
+
+	unsigned int cs_setup;
+	unsigned int rd_setup;
+	unsigned int rd_latch;
+	unsigned int rd_cycle;
+	unsigned int rd_hold;
+	unsigned int wr_setup;
+	unsigned int wr_cycle;
+	unsigned int wr_hold;
+};
+
+#define MIPI_DBI_FLAG_ALIGN_LEFT	(1 << 0)
+
+struct mipi_dbi_device {
+	const char *name;
+	int id;
+	struct device dev;
+
+	const struct mipi_dbi_device_id *id_entry;
+	struct mipi_dbi_bus *bus;
+
+	unsigned int flags;
+	unsigned int bus_width;
+	unsigned int data_width;
+};
+
+#define to_mipi_dbi_device(d)	container_of(d, struct mipi_dbi_device, dev)
+
+int mipi_dbi_device_register(struct mipi_dbi_device *dev,
+			     struct mipi_dbi_bus *bus);
+void mipi_dbi_device_unregister(struct mipi_dbi_device *dev);
+
+struct mipi_dbi_driver {
+	int(*probe)(struct mipi_dbi_device *);
+	int(*remove)(struct mipi_dbi_device *);
+	struct device_driver driver;
+	const struct mipi_dbi_device_id *id_table;
+};
+
+#define to_mipi_dbi_driver(d)	container_of(d, struct mipi_dbi_driver, driver)
+
+int mipi_dbi_driver_register(struct mipi_dbi_driver *drv);
+void mipi_dbi_driver_unregister(struct mipi_dbi_driver *drv);
+
+static inline void *mipi_dbi_get_drvdata(const struct mipi_dbi_device *dev)
+{
+	return dev_get_drvdata(&dev->dev);
+}
+
+static inline void mipi_dbi_set_drvdata(struct mipi_dbi_device *dev,
+					void *data)
+{
+	dev_set_drvdata(&dev->dev, data);
+}
+
+/* module_mipi_dbi_driver() - Helper macro for drivers that don't do
+ * anything special in module init/exit.  This eliminates a lot of
+ * boilerplate.  Each module may only use this macro once, and
+ * calling it replaces module_init() and module_exit()
+ */
+#define module_mipi_dbi_driver(__mipi_dbi_driver) \
+	module_driver(__mipi_dbi_driver, mipi_dbi_driver_register, \
+			mipi_dbi_driver_unregister)
+
+int mipi_dbi_set_data_width(struct mipi_dbi_device *dev, unsigned int width);
+
+int mipi_dbi_write_command(struct mipi_dbi_device *dev, u16 cmd);
+int mipi_dbi_read_data(struct mipi_dbi_device *dev, u8 *data, size_t len);
+int mipi_dbi_write_data(struct mipi_dbi_device *dev, const u8 *data,
+			size_t len);
+
+#endif /* __MIPI_DBI_BUS__ */
-- 
1.8.1.5

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [PATCH/RFC v3 09/19] video: panel: Add DPI panel support
  2013-08-09 17:14 [PATCH/RFC v3 00/19] Common Display Framework Laurent Pinchart
                   ` (7 preceding siblings ...)
  2013-08-09 17:14 ` [PATCH/RFC v3 08/19] video: display: Add MIPI DBI bus support Laurent Pinchart
@ 2013-08-09 17:15 ` Laurent Pinchart
  2013-08-09 17:15 ` [PATCH/RFC v3 10/19] video: panel: Add R61505 " Laurent Pinchart
                   ` (12 subsequent siblings)
  21 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2013-08-09 17:15 UTC (permalink / raw)
  To: dri-devel, linux-fbdev, linux-media
  Cc: Sebastien Guiriec, Jesse Barnes, Benjamin Gaignard, Tom Gall,
	Kyungmin Park, Tomi Valkeinen, Stephen Warren, Mark Zhang,
	Stéphane Marchesin, Alexandre Courbot, Ragesh Radhakrishnan,
	Thomas Petazzoni, Sunil Joshi, Maxime Ripard, Vikas Sajjan,
	Marcus Lorentzon

The Display Pixel Interface is a configurable-width video-only
unidirectional parallel bus standard that defines video formats and
signaling for panel devices.

This driver implements support for simple DPI panels with no runtime
configuration capabilities (GPIOs- and/or regulators-based control can
be implemented later when needed) and exposes it as a display entity.
The panel native video mode is passed to the driver through platform
data or device tree properties.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/video/display/Kconfig     |  10 ++
 drivers/video/display/Makefile    |   1 +
 drivers/video/display/panel-dpi.c | 207 ++++++++++++++++++++++++++++++++++++++
 include/video/panel-dpi.h         |  24 +++++
 4 files changed, 242 insertions(+)
 create mode 100644 drivers/video/display/panel-dpi.c
 create mode 100644 include/video/panel-dpi.h

diff --git a/drivers/video/display/Kconfig b/drivers/video/display/Kconfig
index f7532c1..bce09d6 100644
--- a/drivers/video/display/Kconfig
+++ b/drivers/video/display/Kconfig
@@ -9,4 +9,14 @@ config DISPLAY_MIPI_DBI
 	tristate
 	default n
 
+config DISPLAY_PANEL_DPI
+	tristate "DPI (Parallel) Display Panels"
+	---help---
+	  Support for simple digital (parallel) pixel interface panels. Those
+	  panels receive pixel data through a parallel bus and have no control
+	  bus.
+
+	  If you are in doubt, say N. To compile this driver as a module, choose
+	  M here; the module will be called panel-dpi.
+
 endif # DISPLAY_CORE
diff --git a/drivers/video/display/Makefile b/drivers/video/display/Makefile
index 59022d2..31c017b 100644
--- a/drivers/video/display/Makefile
+++ b/drivers/video/display/Makefile
@@ -2,3 +2,4 @@ display-y					:= display-core.o \
 						   display-notifier.o
 obj-$(CONFIG_DISPLAY_CORE)			+= display.o
 obj-$(CONFIG_DISPLAY_MIPI_DBI)			+= mipi-dbi-bus.o
+obj-$(CONFIG_DISPLAY_PANEL_DPI)			+= panel-dpi.o
diff --git a/drivers/video/display/panel-dpi.c b/drivers/video/display/panel-dpi.c
new file mode 100644
index 0000000..b1ecf6d
--- /dev/null
+++ b/drivers/video/display/panel-dpi.c
@@ -0,0 +1,207 @@
+/*
+ * DPI Display Panel
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <video/display.h>
+#include <video/of_display_timing.h>
+#include <video/of_videomode.h>
+#include <video/panel-dpi.h>
+#include <video/videomode.h>
+
+struct panel_dpi {
+	struct display_entity entity;
+
+	unsigned int width;
+	unsigned int height;
+	struct videomode mode;
+};
+
+static inline struct panel_dpi *to_panel_dpi(struct display_entity *e)
+{
+	return container_of(e, struct panel_dpi, entity);
+}
+
+static const struct display_entity_interface_params panel_dpi_params = {
+	.type = DISPLAY_ENTITY_INTERFACE_DPI,
+};
+
+static int panel_dpi_set_state(struct display_entity *entity,
+			       enum display_entity_state state)
+{
+	struct media_pad *source;
+
+	source = media_entity_remote_pad(&entity->entity.pads[0]);
+	if (source == NULL)
+		return -EPIPE;
+
+	switch (state) {
+	case DISPLAY_ENTITY_STATE_OFF:
+	case DISPLAY_ENTITY_STATE_STANDBY:
+		display_entity_set_stream(to_display_entity(source->entity),
+					  source->index,
+					  DISPLAY_ENTITY_STREAM_STOPPED);
+		break;
+
+	case DISPLAY_ENTITY_STATE_ON:
+		display_entity_set_stream(to_display_entity(source->entity),
+					  source->index,
+					  DISPLAY_ENTITY_STREAM_CONTINUOUS);
+		break;
+	}
+
+	return 0;
+}
+
+static int panel_dpi_get_modes(struct display_entity *entity, unsigned int port,
+			       const struct videomode **modes)
+{
+	struct panel_dpi *panel = to_panel_dpi(entity);
+
+	*modes = &panel->mode;
+	return 1;
+}
+
+static int panel_dpi_get_size(struct display_entity *entity,
+			      unsigned int *width, unsigned int *height)
+{
+	struct panel_dpi *panel = to_panel_dpi(entity);
+
+	*width = panel->width;
+	*height = panel->height;
+	return 0;
+}
+
+static int panel_dpi_get_params(struct display_entity *entity,
+				unsigned int port,
+				struct display_entity_interface_params *params)
+{
+	*params = panel_dpi_params;
+	return 0;
+}
+
+static const struct display_entity_control_ops panel_dpi_control_ops = {
+	.set_state = panel_dpi_set_state,
+	.get_modes = panel_dpi_get_modes,
+	.get_size = panel_dpi_get_size,
+	.get_params = panel_dpi_get_params,
+};
+
+static const struct display_entity_ops panel_dpi_ops = {
+	.ctrl = &panel_dpi_control_ops,
+};
+
+static int panel_dpi_remove(struct platform_device *pdev)
+{
+	struct panel_dpi *panel = platform_get_drvdata(pdev);
+
+	display_entity_remove(&panel->entity);
+	display_entity_cleanup(&panel->entity);
+
+	return 0;
+}
+
+static int panel_dpi_parse_pdata(struct panel_dpi *panel,
+				 struct platform_device *pdev)
+{
+	const struct panel_dpi_platform_data *pdata = pdev->dev.platform_data;
+	struct device_node *np = pdev->dev.of_node;
+	int ret;
+
+	if (pdata) {
+		panel->width = pdata->width;
+		panel->height = pdata->height;
+		panel->mode = *pdata->mode;
+	} else if (IS_ENABLED(CONFIG_OF) && np) {
+		/* Width and height are optional. */
+		of_property_read_u32(np, "width-mm", &panel->width);
+		of_property_read_u32(np, "height-mm", &panel->height);
+
+		ret = of_get_videomode(np, &panel->mode, OF_USE_NATIVE_MODE);
+		if (ret < 0)
+			return ret;
+	} else {
+		dev_err(&pdev->dev, "no platform data\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int panel_dpi_probe(struct platform_device *pdev)
+{
+	struct panel_dpi *panel;
+	int ret;
+
+	panel = devm_kzalloc(&pdev->dev, sizeof(*panel), GFP_KERNEL);
+	if (panel == NULL)
+		return -ENOMEM;
+
+	ret = panel_dpi_parse_pdata(panel, pdev);
+	if (ret < 0)
+		return ret;
+
+	panel->entity.dev = &pdev->dev;
+	panel->entity.ops = &panel_dpi_ops;
+	strlcpy(panel->entity.name, "panel-dpi", sizeof(panel->entity.name));
+
+	ret = display_entity_init(&panel->entity, 1, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = display_entity_add(&panel->entity);
+	if (ret < 0)
+		return ret;
+
+	platform_set_drvdata(pdev, panel);
+
+	return 0;
+}
+
+static const struct dev_pm_ops panel_dpi_dev_pm_ops = {
+};
+
+static struct platform_device_id panel_dpi_id_table[] = {
+	{ "panel-dpi", 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(platform, panel_dpi_id_table);
+
+#ifdef CONFIG_OF
+static struct of_device_id panel_dpi_of_id_table[] = {
+	{ .compatible = "panel-dpi", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, panel_dpi_of_id_table);
+#endif
+
+static struct platform_driver panel_dpi_driver = {
+	.probe = panel_dpi_probe,
+	.remove = panel_dpi_remove,
+	.id_table = panel_dpi_id_table,
+	.driver = {
+		.name = "panel-dpi",
+		.owner = THIS_MODULE,
+		.pm = &panel_dpi_dev_pm_ops,
+		.of_match_table = of_match_ptr(panel_dpi_of_id_table),
+	},
+};
+
+module_platform_driver(panel_dpi_driver);
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_DESCRIPTION("DPI Display Panel");
+MODULE_LICENSE("GPL");
diff --git a/include/video/panel-dpi.h b/include/video/panel-dpi.h
new file mode 100644
index 0000000..af85d5b
--- /dev/null
+++ b/include/video/panel-dpi.h
@@ -0,0 +1,24 @@
+/*
+ * DPI Display Panel
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * 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.
+ */
+
+#ifndef __PANEL_DPI_H__
+#define __PANEL_DPI_H__
+
+struct videomode;
+
+struct panel_dpi_platform_data {
+	unsigned long width;		/* Panel width in mm */
+	unsigned long height;		/* Panel height in mm */
+	const struct videomode *mode;
+};
+
+#endif /* __PANEL_DPI_H__ */
-- 
1.8.1.5

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [PATCH/RFC v3 10/19] video: panel: Add R61505 panel support
  2013-08-09 17:14 [PATCH/RFC v3 00/19] Common Display Framework Laurent Pinchart
                   ` (8 preceding siblings ...)
  2013-08-09 17:15 ` [PATCH/RFC v3 09/19] video: panel: Add DPI panel support Laurent Pinchart
@ 2013-08-09 17:15 ` Laurent Pinchart
  2013-08-09 17:15 ` [PATCH/RFC v3 11/19] video: panel: Add R61517 " Laurent Pinchart
                   ` (11 subsequent siblings)
  21 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2013-08-09 17:15 UTC (permalink / raw)
  To: dri-devel, linux-fbdev, linux-media
  Cc: Sebastien Guiriec, Jesse Barnes, Benjamin Gaignard, Tom Gall,
	Kyungmin Park, Tomi Valkeinen, Stephen Warren, Mark Zhang,
	Stéphane Marchesin, Alexandre Courbot, Ragesh Radhakrishnan,
	Thomas Petazzoni, Sunil Joshi, Maxime Ripard, Vikas Sajjan,
	Marcus Lorentzon

The R61505 is a SYS-80 bus panel controller from Renesas.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/video/display/Kconfig        |  10 +
 drivers/video/display/Makefile       |   1 +
 drivers/video/display/panel-r61505.c | 567 +++++++++++++++++++++++++++++++++++
 include/video/panel-r61505.h         |  27 ++
 4 files changed, 605 insertions(+)
 create mode 100644 drivers/video/display/panel-r61505.c
 create mode 100644 include/video/panel-r61505.h

diff --git a/drivers/video/display/Kconfig b/drivers/video/display/Kconfig
index bce09d6..76729ef 100644
--- a/drivers/video/display/Kconfig
+++ b/drivers/video/display/Kconfig
@@ -19,4 +19,14 @@ config DISPLAY_PANEL_DPI
 	  If you are in doubt, say N. To compile this driver as a module, choose
 	  M here; the module will be called panel-dpi.
 
+config DISPLAY_PANEL_R61505
+	tristate "Renesas R61505-based Display Panel"
+	select DISPLAY_MIPI_DBI
+	---help---
+	  Support panels based on the Renesas R61505 panel controller.
+	  Those panels are controlled through a MIPI DBI interface.
+
+	  If you are in doubt, say N. To compile this driver as a module, choose
+	  M here; the module will be called panel-r61505.
+
 endif # DISPLAY_CORE
diff --git a/drivers/video/display/Makefile b/drivers/video/display/Makefile
index 31c017b..db8a4c3 100644
--- a/drivers/video/display/Makefile
+++ b/drivers/video/display/Makefile
@@ -3,3 +3,4 @@ display-y					:= display-core.o \
 obj-$(CONFIG_DISPLAY_CORE)			+= display.o
 obj-$(CONFIG_DISPLAY_MIPI_DBI)			+= mipi-dbi-bus.o
 obj-$(CONFIG_DISPLAY_PANEL_DPI)			+= panel-dpi.o
+obj-$(CONFIG_DISPLAY_PANEL_R61505)		+= panel-r61505.o
diff --git a/drivers/video/display/panel-r61505.c b/drivers/video/display/panel-r61505.c
new file mode 100644
index 0000000..c86177e
--- /dev/null
+++ b/drivers/video/display/panel-r61505.c
@@ -0,0 +1,567 @@
+/*
+ * Renesas R61505-based Display Panels
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ * Based on SuperH MigoR Quarter VGA LCD Panel
+ * Copyright (C) 2008 Magnus Damm
+ * Based on lcd_powertip.c from Kenati Technologies Pvt Ltd.
+ * Copyright (c) 2007 Ujjwal Pande
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * 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.
+ */
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <video/display.h>
+#include <video/mipi-dbi-bus.h>
+#include <video/panel-r61505.h>
+#include <video/videomode.h>
+
+#define R61505_DEVICE_CODE			0x0000
+#define R61505_DEVICE_CODE_VALUE		0x1505
+#define R61505_DRIVER_OUTPUT_CONTROL		0x0001
+#define R61505_DRIVER_OUTPUT_CONTROL_SM		(1 << 10)
+#define R61505_DRIVER_OUTPUT_CONTROL_SS		(1 << 8)
+#define R61505_LCD_WAVEFORM			0x0002
+#define R61505_LCD_WAVEFORM_BC0			(1 << 9)
+#define R61505_LCD_WAVEFORM_EOR			(1 << 8)
+#define R61505_ENTRY_MODE			0x0003
+#define R61505_ENTRY_MODE_TRIREG		(1 << 15)
+#define R61505_ENTRY_MODE_DFM			(1 << 14)
+#define R61505_ENTRY_MODE_BGR			(1 << 12)
+#define R61505_ENTRY_MODE_HWM			(1 << 9)
+#define R61505_ENTRY_MODE_ORG			(1 << 7)
+#define R61505_ENTRY_MODE_ID1			(1 << 5)
+#define R61505_ENTRY_MODE_ID0			(1 << 4)
+#define R61505_ENTRY_MODE_AM			(1 << 3)
+#define R61505_RESIZE_CONTROL			0x0004
+#define R61505_RESIZE_CONTROL_RCV(n)		(((n) & 3) << 8)
+#define R61505_RESIZE_CONTROL_RCH(n)		(((n) & 3) << 4)
+#define R61505_RESIZE_CONTROL_RSZ_4		(3 << 0)
+#define R61505_RESIZE_CONTROL_RSZ_2		(1 << 0)
+#define R61505_RESIZE_CONTROL_RSZ_1		(0 << 0)
+#define R61505_DISPLAY_CONTROL1			0x0007
+#define R61505_DISPLAY_CONTROL1_PTDE1		(1 << 13)
+#define R61505_DISPLAY_CONTROL1_PTDE0		(1 << 12)
+#define R61505_DISPLAY_CONTROL1_BASEE		(1 << 8)
+#define R61505_DISPLAY_CONTROL1_VON		(1 << 6)
+#define R61505_DISPLAY_CONTROL1_GON		(1 << 5)
+#define R61505_DISPLAY_CONTROL1_DTE		(1 << 4)
+#define R61505_DISPLAY_CONTROL1_COL		(1 << 3)
+#define R61505_DISPLAY_CONTROL1_D1		(1 << 1)
+#define R61505_DISPLAY_CONTROL1_D0		(1 << 0)
+#define R61505_DISPLAY_CONTROL2			0x0008
+#define R61505_DISPLAY_CONTROL2_FP(n)		(((n) & 0xf) << 8)
+#define R61505_DISPLAY_CONTROL2_BP(n)		(((n) & 0xf) << 0)
+#define R61505_DISPLAY_CONTROL3			0x0009
+#define R61505_DISPLAY_CONTROL3_PTS(n)		(((n) & 7) << 8)
+#define R61505_DISPLAY_CONTROL3_PTG(n)		(((n) & 3) << 3)
+#define R61505_DISPLAY_CONTROL3_ICS(n)		(((n) & 0xf) << 0)
+#define R61505_DISPLAY_CONTROL4			0x000a
+#define R61505_DISPLAY_CONTROL4_FMARKOE		(1 << 3)
+#define R61505_DISPLAY_CONTROL4_FMI_6		(5 << 0)
+#define R61505_DISPLAY_CONTROL4_FMI_4		(3 << 0)
+#define R61505_DISPLAY_CONTROL4_FMI_2		(1 << 0)
+#define R61505_DISPLAY_CONTROL4_FMI_1		(0 << 0)
+#define R61505_EXT_DISPLAY_IF_CONTROL1		0x000c
+#define R61505_EXT_DISPLAY_IF_CONTROL1_ENC(n)	(((n) & 7) << 12)
+#define R61505_EXT_DISPLAY_IF_CONTROL1_RM	(1 << 8)
+#define R61505_EXT_DISPLAY_IF_CONTROL1_DM_VSYNC	(2 << 4)
+#define R61505_EXT_DISPLAY_IF_CONTROL1_DM_RGB	(1 << 4)
+#define R61505_EXT_DISPLAY_IF_CONTROL1_DM_ICLK	(0 << 4)
+#define R61505_EXT_DISPLAY_IF_CONTROL1_RIM_6	(2 << 0)
+#define R61505_EXT_DISPLAY_IF_CONTROL1_RIM_16	(1 << 0)
+#define R61505_EXT_DISPLAY_IF_CONTROL1_RIM_18	(0 << 0)
+#define R61505_FRAME_MARKER_CONTROL		0x000d
+#define R61505_FRAME_MARKER_CONTROL_FMP(n)	(((n) & 0x1ff) << 0)
+#define R61505_EXT_DISPLAY_IF_CONTROL2		0x000f
+#define R61505_POWER_CONTROL1			0x0010
+#define R61505_POWER_CONTROL1_SAP		(1 << 12)
+#define R61505_POWER_CONTROL1_BT(n)		(((n) & 0xf) << 8)
+#define R61505_POWER_CONTROL1_APE		(1 << 7)
+#define R61505_POWER_CONTROL1_AP_100		(3 << 4)
+#define R61505_POWER_CONTROL1_AP_075		(2 << 4)
+#define R61505_POWER_CONTROL1_AP_050		(1 << 4)
+#define R61505_POWER_CONTROL1_AP_HALT		(0 << 4)
+#define R61505_POWER_CONTROL1_DSTB		(1 << 2)
+#define R61505_POWER_CONTROL1_SLP		(1 << 1)
+#define R61505_POWER_CONTROL2			0x0011
+#define R61505_POWER_CONTROL2_DC1_HALT		(6 << 8)
+#define R61505_POWER_CONTROL2_DC1_FOSC_256	(4 << 8)
+#define R61505_POWER_CONTROL2_DC1_FOSC_128	(3 << 8)
+#define R61505_POWER_CONTROL2_DC1_FOSC_64	(2 << 8)
+#define R61505_POWER_CONTROL2_DC1_FOSC_32	(1 << 8)
+#define R61505_POWER_CONTROL2_DC1_FOSC_16	(0 << 8)
+#define R61505_POWER_CONTROL2_DC0_HALT		(6 << 4)
+#define R61505_POWER_CONTROL2_DC0_FOSC_16	(4 << 4)
+#define R61505_POWER_CONTROL2_DC0_FOSC_8	(3 << 4)
+#define R61505_POWER_CONTROL2_DC0_FOSC_4	(2 << 4)
+#define R61505_POWER_CONTROL2_DC0_FOSC_2	(1 << 4)
+#define R61505_POWER_CONTROL2_DC0_FOSC		(0 << 4)
+#define R61505_POWER_CONTROL2_VC_100		(7 << 0)
+#define R61505_POWER_CONTROL2_VC_076		(4 << 0)
+#define R61505_POWER_CONTROL2_VC_089		(1 << 0)
+#define R61505_POWER_CONTROL2_VC_094		(0 << 0)
+#define R61505_POWER_CONTROL3			0x0012
+#define R61505_POWER_CONTROL3_VCMR		(1 << 8)
+#define R61505_POWER_CONTROL3_PSON		(1 << 5)
+#define R61505_POWER_CONTROL3_PON		(1 << 4)
+#define R61505_POWER_CONTROL3_VRH(n)		(((n) & 0xf) << 0)
+#define R61505_POWER_CONTROL4			0x0013
+#define R61505_POWER_CONTROL4_VDV(n)		(((n) & 0xf) << 8)
+#define R61505_POWER_CONTROL5			0x0015
+#define R61505_POWER_CONTROL5_BLDM		(1 << 12)
+#define R61505_POWER_CONTROL6			0x0017
+#define R61505_POWER_CONTROL6_PSE		(1 << 0)
+#define R61505_RAM_ADDR_HORZ			0x0020
+#define R61505_RAM_ADDR_VERT			0x0021
+#define R61505_RAM_DATA				0x0022
+#define R61505_POWER_CONTROL7			0x0029
+#define R61505_POWER_CONTROL7_VCM1(n)		(((n) & 0x1f) << 0)
+#define R61505_GAMMA_CONTROL1			0x0030
+#define R61505_GAMMA_CONTROL2			0x0031
+#define R61505_GAMMA_CONTROL3			0x0032
+#define R61505_GAMMA_CONTROL4			0x0033
+#define R61505_GAMMA_CONTROL5			0x0034
+#define R61505_GAMMA_CONTROL6			0x0035
+#define R61505_GAMMA_CONTROL7			0x0036
+#define R61505_GAMMA_CONTROL8			0x0037
+#define R61505_GAMMA_CONTROL9			0x0038
+#define R61505_GAMMA_CONTROL10			0x0039
+#define R61505_GAMMA_CONTROL11			0x003a
+#define R61505_GAMMA_CONTROL12			0x003b
+#define R61505_GAMMA_CONTROL13			0x003c
+#define R61505_GAMMA_CONTROL14			0x003d
+#define R61505_WINDOW_HORZ_START		0x0050
+#define R61505_WINDOW_HORZ_END			0x0051
+#define R61505_WINDOW_VERT_START		0x0052
+#define R61505_WINDOW_VERT_END			0x0053
+#define R61505_DRIVER_OUTPUT_CONTROL2		0x0060
+#define R61505_DRIVER_OUTPUT_CONTROL2_GS	(1 << 15)
+#define R61505_DRIVER_OUTPUT_CONTROL2_NL(n)	(((n) & 0x3f) << 8)
+#define R61505_DRIVER_OUTPUT_CONTROL2_SCN(n)	(((n) & 0x3f) << 0)
+#define R61505_BASE_IMG_DISPLAY_CONTROL		0x0061
+#define R61505_BASE_IMG_DISPLAY_CONTROL_NDL	(1 << 2)
+#define R61505_BASE_IMG_DISPLAY_CONTROL_VLE	(1 << 1)
+#define R61505_BASE_IMG_DISPLAY_CONTROL_REV	(1 << 0)
+#define R61505_VERTICAL_SCROLL_CONTROL		0x006a
+#define R61505_PANEL_IF_CONTROL1		0x0090
+#define R61505_PANEL_IF_CONTROL1_DIVI(n)	(((n) & 3) << 8)
+#define R61505_PANEL_IF_CONTROL1_RTNI(n)	(((n) & 0x1f) << 0)
+#define R61505_PANEL_IF_CONTROL2		0x0092
+#define R61505_PANEL_IF_CONTROL2_NOWI(n)	(((n) & 7) << 8)
+#define R61505_PANEL_IF_CONTROL3		0x0093
+#define R61505_PANEL_IF_CONTROL3_MCP(n)		(((n) & 7) << 8)
+#define R61505_PANEL_IF_CONTROL4		0x0095
+#define R61505_PANEL_IF_CONTROL5		0x0097
+#define R61505_PANEL_IF_CONTROL6		0x0098
+#define R61505_OSCILLATION_CONTROL		0x00a4
+#define R61505_OSCILLATION_CONTROL_CALB		(1 << 0)
+
+struct r61505 {
+	struct display_entity entity;
+	struct mipi_dbi_device *dbi;
+	const struct panel_r61505_platform_data *pdata;
+};
+
+static inline struct r61505 *to_panel(struct display_entity *e)
+{
+	return container_of(e, struct r61505, entity);
+}
+
+/* -----------------------------------------------------------------------------
+ * Read, write and reset
+ */
+
+static void r61505_write(struct r61505 *panel, u16 reg, u16 data)
+{
+	u8 buffer[2] = { data >> 8, data & 0xff };
+
+	mipi_dbi_write_command(panel->dbi, reg);
+	mipi_dbi_write_data(panel->dbi, buffer, 2);
+}
+
+static u16 r61505_read(struct r61505 *panel, u16 reg)
+{
+	u8 buffer[2];
+	int ret;
+
+	mipi_dbi_write_command(panel->dbi, reg);
+	ret = mipi_dbi_read_data(panel->dbi, buffer, 2);
+	if (ret < 0)
+		return ret;
+
+	return (buffer[0] << 8) | buffer[1];
+}
+
+static void r61505_write_array(struct r61505 *panel,
+				 const u16 *data, unsigned int len)
+{
+	unsigned int i;
+
+	for (i = 0; i < len; i += 2)
+		r61505_write(panel, data[i], data[i + 1]);
+}
+
+static void r61505_reset(struct r61505 *panel)
+{
+	if (panel->pdata->reset < 0)
+		return;
+
+	gpio_set_value(panel->pdata->reset, 0);
+	usleep_range(2000, 2500);
+	gpio_set_value(panel->pdata->reset, 1);
+	usleep_range(1000, 1500);
+}
+
+/* -----------------------------------------------------------------------------
+ * Configuration
+ */
+
+static const unsigned short sync_data[] = {
+	0x0000, 0x0000,
+	0x0000, 0x0000,
+	0x0000, 0x0000,
+	0x0000, 0x0000,
+};
+
+static const unsigned short magic0_data[] = {
+	R61505_DISPLAY_CONTROL2, R61505_DISPLAY_CONTROL2_FP(8) |
+				 R61505_DISPLAY_CONTROL2_BP(8),
+	R61505_PANEL_IF_CONTROL1, R61505_PANEL_IF_CONTROL1_RTNI(26),
+	R61505_DISPLAY_CONTROL1, R61505_DISPLAY_CONTROL1_D0,
+	R61505_POWER_CONTROL6, R61505_POWER_CONTROL6_PSE,
+	0x0019, 0x0000,
+	R61505_POWER_CONTROL1, R61505_POWER_CONTROL1_SAP |
+			       R61505_POWER_CONTROL1_BT(7) |
+			       R61505_POWER_CONTROL1_APE |
+			       R61505_POWER_CONTROL1_AP_100,
+	R61505_POWER_CONTROL2, R61505_POWER_CONTROL2_DC1_FOSC_32 |
+			       R61505_POWER_CONTROL2_DC0_FOSC_2 | 6,
+	R61505_POWER_CONTROL3, R61505_POWER_CONTROL3_VCMR | 0x80 |
+			       R61505_POWER_CONTROL3_PON |
+			       R61505_POWER_CONTROL3_VRH(8),
+	R61505_POWER_CONTROL4, 0x1000 | R61505_POWER_CONTROL4_VDV(4),
+	R61505_POWER_CONTROL7, R61505_POWER_CONTROL7_VCM1(12),
+	R61505_POWER_CONTROL3, R61505_POWER_CONTROL3_VCMR | 0x80 |
+			       R61505_POWER_CONTROL3_PSON |
+			       R61505_POWER_CONTROL3_PON |
+			       R61505_POWER_CONTROL3_VRH(8),
+};
+
+static const unsigned short magic1_data[] = {
+	R61505_GAMMA_CONTROL1, 0x0307,
+	R61505_GAMMA_CONTROL2, 0x0303,
+	R61505_GAMMA_CONTROL3, 0x0603,
+	R61505_GAMMA_CONTROL4, 0x0202,
+	R61505_GAMMA_CONTROL5, 0x0202,
+	R61505_GAMMA_CONTROL6, 0x0202,
+	R61505_GAMMA_CONTROL7, 0x1f1f,
+	R61505_GAMMA_CONTROL8, 0x0303,
+	R61505_GAMMA_CONTROL9, 0x0303,
+	R61505_GAMMA_CONTROL10, 0x0603,
+	R61505_GAMMA_CONTROL11, 0x0202,
+	R61505_GAMMA_CONTROL12, 0x0102,
+	R61505_GAMMA_CONTROL13, 0x0204,
+	R61505_GAMMA_CONTROL14, 0x0000,
+	R61505_DRIVER_OUTPUT_CONTROL, R61505_DRIVER_OUTPUT_CONTROL_SS,
+	R61505_LCD_WAVEFORM, R61505_LCD_WAVEFORM_BC0 |
+			     R61505_LCD_WAVEFORM_EOR,
+	R61505_ENTRY_MODE, R61505_ENTRY_MODE_DFM |
+			   R61505_ENTRY_MODE_BGR |
+			   R61505_ENTRY_MODE_ID1 |
+			   R61505_ENTRY_MODE_AM,
+	R61505_RAM_ADDR_HORZ, 239,
+	R61505_RAM_ADDR_VERT, 0,
+	R61505_RESIZE_CONTROL, R61505_RESIZE_CONTROL_RCV(0) |
+			       R61505_RESIZE_CONTROL_RCH(0) |
+			       R61505_RESIZE_CONTROL_RSZ_1,
+	R61505_DISPLAY_CONTROL3, R61505_DISPLAY_CONTROL3_PTS(0) |
+				 R61505_DISPLAY_CONTROL3_PTG(0) |
+				 R61505_DISPLAY_CONTROL3_ICS(0),
+	R61505_DISPLAY_CONTROL4, R61505_DISPLAY_CONTROL4_FMARKOE |
+				 R61505_DISPLAY_CONTROL4_FMI_1,
+	R61505_EXT_DISPLAY_IF_CONTROL1, R61505_EXT_DISPLAY_IF_CONTROL1_ENC(0) |
+					R61505_EXT_DISPLAY_IF_CONTROL1_DM_ICLK |
+					R61505_EXT_DISPLAY_IF_CONTROL1_RIM_18,
+	R61505_FRAME_MARKER_CONTROL, R61505_FRAME_MARKER_CONTROL_FMP(0),
+	R61505_POWER_CONTROL5, 0x8000,
+};
+
+static const unsigned short magic2_data[] = {
+	R61505_BASE_IMG_DISPLAY_CONTROL, R61505_BASE_IMG_DISPLAY_CONTROL_REV,
+	R61505_PANEL_IF_CONTROL2, R61505_PANEL_IF_CONTROL2_NOWI(1),
+	R61505_PANEL_IF_CONTROL3, R61505_PANEL_IF_CONTROL3_MCP(1),
+	R61505_DISPLAY_CONTROL1, R61505_DISPLAY_CONTROL1_GON |
+				 R61505_DISPLAY_CONTROL1_D0,
+};
+
+static const unsigned short magic3_data[] = {
+	R61505_POWER_CONTROL1, R61505_POWER_CONTROL1_SAP |
+			       R61505_POWER_CONTROL1_BT(6) |
+			       R61505_POWER_CONTROL1_APE |
+			       R61505_POWER_CONTROL1_AP_100,
+	R61505_POWER_CONTROL2, R61505_POWER_CONTROL2_DC1_FOSC_32 |
+			       R61505_POWER_CONTROL2_DC0_FOSC_2 |
+			       R61505_POWER_CONTROL2_VC_089,
+	R61505_DISPLAY_CONTROL1, R61505_DISPLAY_CONTROL1_VON |
+				 R61505_DISPLAY_CONTROL1_GON |
+				 R61505_DISPLAY_CONTROL1_D0,
+};
+
+static void r61505_enable_panel(struct r61505 *panel)
+{
+	unsigned long hactive = panel->pdata->mode->hactive;
+	unsigned long vactive = panel->pdata->mode->vactive;
+	unsigned int i;
+
+	r61505_write_array(panel, sync_data, ARRAY_SIZE(sync_data));
+
+	r61505_write(panel, R61505_OSCILLATION_CONTROL,
+		     R61505_OSCILLATION_CONTROL_CALB);
+	usleep_range(10000, 11000);
+
+	r61505_write(panel, R61505_DRIVER_OUTPUT_CONTROL2,
+		     R61505_DRIVER_OUTPUT_CONTROL2_NL((hactive / 8) - 1));
+	r61505_write_array(panel, magic0_data, ARRAY_SIZE(magic0_data));
+	usleep_range(100000, 101000);
+
+	r61505_write_array(panel, magic1_data, ARRAY_SIZE(magic1_data));
+
+	r61505_write(panel, R61505_WINDOW_HORZ_START, 239 - (vactive - 1));
+	r61505_write(panel, R61505_WINDOW_HORZ_END, 239);
+	r61505_write(panel, R61505_WINDOW_VERT_START, 0);
+	r61505_write(panel, R61505_WINDOW_VERT_END, hactive - 1);
+
+	r61505_write_array(panel, magic2_data, ARRAY_SIZE(magic2_data));
+	usleep_range(10000, 11000);
+
+	r61505_write_array(panel, magic3_data, ARRAY_SIZE(magic3_data));
+	usleep_range(40000, 41000);
+
+	/* Clear GRAM to avoid displaying garbage. */
+	r61505_write(panel, R61505_RAM_ADDR_HORZ, 0);
+	r61505_write(panel, R61505_RAM_ADDR_VERT, 0);
+
+	for (i = 0; i < (hactive * 256); i++) /* yes, 256 words per line */
+		r61505_write(panel, R61505_RAM_DATA, 0);
+
+	r61505_write(panel, R61505_RAM_ADDR_HORZ, 0);
+	r61505_write(panel, R61505_RAM_ADDR_VERT, 0);
+}
+
+static void r61505_disable_panel(struct r61505 *panel)
+{
+	r61505_reset(panel);
+}
+
+static void r61505_display_on(struct r61505 *panel)
+{
+	r61505_write(panel, R61505_DISPLAY_CONTROL1,
+		     R61505_DISPLAY_CONTROL1_BASEE |
+		     R61505_DISPLAY_CONTROL1_VON |
+		     R61505_DISPLAY_CONTROL1_GON |
+		     R61505_DISPLAY_CONTROL1_DTE |
+		     R61505_DISPLAY_CONTROL1_D1 |
+		     R61505_DISPLAY_CONTROL1_D0);
+	usleep_range(40000, 41000);
+}
+
+static void r61505_display_off(struct r61505 *panel)
+{
+	r61505_write(panel, R61505_DISPLAY_CONTROL1,
+		     R61505_DISPLAY_CONTROL1_VON |
+		     R61505_DISPLAY_CONTROL1_GON |
+		     R61505_DISPLAY_CONTROL1_D0);
+}
+
+/* -----------------------------------------------------------------------------
+ * Panel operations
+ */
+
+static const struct display_entity_interface_params r61505_dbi_params = {
+	.type = DISPLAY_ENTITY_INTERFACE_DBI,
+	.p.dbi = {
+		.type = MIPI_DBI_INTERFACE_TYPE_B,
+		.cs_setup = 1,
+		.wr_setup = 0,
+		.wr_cycle = 10,
+		.wr_hold = 9,
+		.rd_setup = 14,
+		.rd_latch = 24,
+		.rd_cycle = 52,
+		.rd_hold = 24,
+	},
+};
+
+static int r61505_set_state(struct display_entity *entity,
+			    enum display_entity_state state)
+{
+	struct r61505 *panel = to_panel(entity);
+
+	switch (state) {
+	case DISPLAY_ENTITY_STATE_OFF:
+		r61505_disable_panel(panel);
+		break;
+
+	case DISPLAY_ENTITY_STATE_STANDBY:
+		if (entity->state == DISPLAY_ENTITY_STATE_OFF)
+			r61505_enable_panel(panel);
+		else
+			r61505_display_off(panel);
+		break;
+
+	case DISPLAY_ENTITY_STATE_ON:
+		if (entity->state == DISPLAY_ENTITY_STATE_OFF)
+			r61505_enable_panel(panel);
+
+		r61505_display_on(panel);
+		break;
+	}
+
+	return 0;
+}
+
+static int r61505_update(struct display_entity *entity)
+{
+	struct r61505 *panel = to_panel(entity);
+	struct media_pad *source;
+
+	mipi_dbi_write_command(panel->dbi, R61505_RAM_DATA);
+	usleep_range(100000, 101000);
+
+	source = media_entity_remote_pad(&entity->entity.pads[0]);
+	if (source == NULL)
+		return -EPIPE;
+
+	display_entity_set_stream(to_display_entity(source->entity),
+				  source->index,
+				  DISPLAY_ENTITY_STREAM_SINGLE_SHOT);
+	return 0;
+}
+
+static int r61505_get_modes(struct display_entity *entity, unsigned int port,
+			    const struct videomode **modes)
+{
+	struct r61505 *panel = to_panel(entity);
+
+	*modes = panel->pdata->mode;
+	return 1;
+}
+
+static int r61505_get_size(struct display_entity *entity,
+			   unsigned int *width, unsigned int *height)
+{
+	struct r61505 *panel = to_panel(entity);
+
+	*width = panel->pdata->width;
+	*height = panel->pdata->height;
+	return 0;
+}
+
+static int r61505_get_params(struct display_entity *entity, unsigned int port,
+			     struct display_entity_interface_params *params)
+{
+	*params = r61505_dbi_params;
+	return 0;
+}
+
+static const struct display_entity_control_ops r61505_control_ops = {
+	.set_state = r61505_set_state,
+	.update = r61505_update,
+	.get_modes = r61505_get_modes,
+	.get_size = r61505_get_size,
+	.get_params = r61505_get_params,
+};
+
+static const struct display_entity_ops r61505_ops = {
+	.ctrl = &r61505_control_ops,
+};
+
+static int r61505_remove(struct mipi_dbi_device *dev)
+{
+	struct r61505 *panel = mipi_dbi_get_drvdata(dev);
+
+	display_entity_remove(&panel->entity);
+	display_entity_cleanup(&panel->entity);
+
+	return 0;
+}
+
+static int r61505_probe(struct mipi_dbi_device *dev)
+{
+	const struct panel_r61505_platform_data *pdata = dev->dev.platform_data;
+	struct r61505 *panel;
+	int ret;
+
+	if (pdata == NULL)
+		return -ENODEV;
+
+	panel = devm_kzalloc(&dev->dev, sizeof(*panel), GFP_KERNEL);
+	if (panel == NULL)
+		return -ENOMEM;
+
+	panel->pdata = pdata;
+	panel->dbi = dev;
+
+	dev->flags = MIPI_DBI_FLAG_ALIGN_LEFT;
+	dev->bus_width = pdata->bus_width;
+	mipi_dbi_set_data_width(dev, 16);
+
+	r61505_reset(panel);
+	r61505_write_array(panel, sync_data, ARRAY_SIZE(sync_data));
+
+	if (r61505_read(panel, 0) != R61505_DEVICE_CODE_VALUE)
+		return -ENODEV;
+
+	panel->entity.dev = &dev->dev;
+	panel->entity.ops = &r61505_ops;
+
+	ret = display_entity_init(&panel->entity, 1, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = display_entity_add(&panel->entity);
+	if (ret < 0)
+		return ret;
+
+	mipi_dbi_set_drvdata(dev, panel);
+
+	return 0;
+}
+
+static const struct dev_pm_ops r61505_dev_pm_ops = {
+};
+
+static struct mipi_dbi_device_id r61505_id_table[] = {
+	{ "panel-r61505", 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(mipi_dbi, r61505_id_table);
+
+static struct mipi_dbi_driver r61505_driver = {
+	.probe = r61505_probe,
+	.remove = r61505_remove,
+	.id_table = r61505_id_table,
+	.driver = {
+		.name = "panel-r61505",
+		.owner = THIS_MODULE,
+		.pm = &r61505_dev_pm_ops,
+	},
+};
+
+module_mipi_dbi_driver(r61505_driver);
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_DESCRIPTION("Renesas R61505-based Display Panel");
+MODULE_LICENSE("GPL");
diff --git a/include/video/panel-r61505.h b/include/video/panel-r61505.h
new file mode 100644
index 0000000..ee71f29
--- /dev/null
+++ b/include/video/panel-r61505.h
@@ -0,0 +1,27 @@
+/*
+ * Renesas R61505-based Display Panels
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * 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.
+ */
+
+#ifndef __PANEL_R61505_H__
+#define __PANEL_R61505_H__
+
+struct videomode;
+
+struct panel_r61505_platform_data {
+	unsigned long width;		/* Panel width in mm */
+	unsigned long height;		/* Panel height in mm */
+	const struct videomode *mode;
+
+	unsigned int bus_width;
+	int reset;			/* Reset GPIO */
+};
+
+#endif /* __PANEL_R61505_H__ */
-- 
1.8.1.5

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [PATCH/RFC v3 11/19] video: panel: Add R61517 panel support
  2013-08-09 17:14 [PATCH/RFC v3 00/19] Common Display Framework Laurent Pinchart
                   ` (9 preceding siblings ...)
  2013-08-09 17:15 ` [PATCH/RFC v3 10/19] video: panel: Add R61505 " Laurent Pinchart
@ 2013-08-09 17:15 ` Laurent Pinchart
  2013-08-09 17:15 ` [PATCH/RFC v3 12/19] video: display: Add VGA Digital to Analog Converter support Laurent Pinchart
                   ` (10 subsequent siblings)
  21 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2013-08-09 17:15 UTC (permalink / raw)
  To: dri-devel, linux-fbdev, linux-media
  Cc: Sebastien Guiriec, Jesse Barnes, Benjamin Gaignard, Tom Gall,
	Kyungmin Park, Tomi Valkeinen, Stephen Warren, Mark Zhang,
	Stéphane Marchesin, Alexandre Courbot, Ragesh Radhakrishnan,
	Thomas Petazzoni, Sunil Joshi, Maxime Ripard, Vikas Sajjan,
	Marcus Lorentzon

The R61517 is a MIPI DBI panel controller from Renesas.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/video/display/Kconfig        |  10 +
 drivers/video/display/Makefile       |   1 +
 drivers/video/display/panel-r61517.c | 460 +++++++++++++++++++++++++++++++++++
 include/video/panel-r61517.h         |  28 +++
 4 files changed, 499 insertions(+)
 create mode 100644 drivers/video/display/panel-r61517.c
 create mode 100644 include/video/panel-r61517.h

diff --git a/drivers/video/display/Kconfig b/drivers/video/display/Kconfig
index 76729ef..9b44b5f 100644
--- a/drivers/video/display/Kconfig
+++ b/drivers/video/display/Kconfig
@@ -29,4 +29,14 @@ config DISPLAY_PANEL_R61505
 	  If you are in doubt, say N. To compile this driver as a module, choose
 	  M here; the module will be called panel-r61505.
 
+config DISPLAY_PANEL_R61517
+	tristate "Renesas R61517-based Display Panel"
+	select DISPLAY_MIPI_DBI
+	---help---
+	  Support panels based on the Renesas R61517 panel controller.
+	  Those panels are controlled through a MIPI DBI interface.
+
+	  If you are in doubt, say N. To compile this driver as a module, choose
+	  M here; the module will be called panel-r61517.
+
 endif # DISPLAY_CORE
diff --git a/drivers/video/display/Makefile b/drivers/video/display/Makefile
index db8a4c3..1cdc8d4 100644
--- a/drivers/video/display/Makefile
+++ b/drivers/video/display/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_DISPLAY_CORE)			+= display.o
 obj-$(CONFIG_DISPLAY_MIPI_DBI)			+= mipi-dbi-bus.o
 obj-$(CONFIG_DISPLAY_PANEL_DPI)			+= panel-dpi.o
 obj-$(CONFIG_DISPLAY_PANEL_R61505)		+= panel-r61505.o
+obj-$(CONFIG_DISPLAY_PANEL_R61517)		+= panel-r61517.o
diff --git a/drivers/video/display/panel-r61517.c b/drivers/video/display/panel-r61517.c
new file mode 100644
index 0000000..ccfec33
--- /dev/null
+++ b/drivers/video/display/panel-r61517.c
@@ -0,0 +1,460 @@
+/*
+ * Renesas R61517-based Display Panels
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ * Based on KFR2R09 LCD panel support
+ * Copyright (C) 2009 Magnus Damm
+ * Register settings based on the out-of-tree t33fb.c driver
+ * Copyright (C) 2008 Lineo Solutions, Inc.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * 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.
+ */
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+
+#include <video/display.h>
+#include <video/mipi-dbi-bus.h>
+#include <video/mipi_display.h>
+#include <video/panel-r61517.h>
+#include <video/videomode.h>
+
+struct r61517 {
+	struct display_entity entity;
+	struct mipi_dbi_device *dbi;
+	const struct panel_r61517_platform_data *pdata;
+};
+
+static inline struct r61517 *to_panel(struct display_entity *e)
+{
+	return container_of(e, struct r61517, entity);
+}
+
+/* -----------------------------------------------------------------------------
+ * Read, write and reset
+ */
+
+static void r61517_write_command(struct r61517 *panel, u16 cmd)
+{
+	mipi_dbi_write_command(panel->dbi, cmd);
+}
+
+static void r61517_write_data(struct r61517 *panel, u8 data)
+{
+	mipi_dbi_write_data(panel->dbi, &data, 1);
+}
+
+static int r61517_read_data(struct r61517 *panel)
+{
+	u8 data;
+	int ret;
+
+	ret = mipi_dbi_read_data(panel->dbi, &data, 1);
+	if (ret < 0)
+		return ret;
+
+	return data;
+}
+
+static void r61517_write(struct r61517 *panel, u8 reg, const u8 *data,
+			 size_t len)
+{
+	mipi_dbi_write_command(panel->dbi, reg);
+	mipi_dbi_write_data(panel->dbi, data, len);
+}
+
+static void r61517_write8(struct r61517 *panel, u8 reg, u8 data)
+{
+	r61517_write(panel, reg, &data, 1);
+}
+
+static void r61517_write16(struct r61517 *panel, u8 reg, u16 data)
+{
+	u8 buffer[2] = { (data >> 8) & 0xff, (data >> 0) & 0xff };
+
+	r61517_write(panel, reg, buffer, 2);
+}
+
+static void r61517_write32(struct r61517 *panel, u8 reg, u32 data)
+{
+	u8 buffer[4] = { (data >> 24) & 0xff, (data >> 16) & 0xff,
+			 (data >>  8) & 0xff, (data >>  0) & 0xff };
+
+	r61517_write(panel, reg, buffer, 4);
+}
+
+#define r61517_write_array(p, c, a) \
+	r61517_write((p), (c), (a), ARRAY_SIZE(a))
+
+static void r61517_reset(struct r61517 *panel)
+{
+	gpio_set_value(panel->pdata->protect, 0);	/* PROTECT/ -> L */
+	gpio_set_value(panel->pdata->reset, 0);		/* LCD_RST/ -> L */
+	gpio_set_value(panel->pdata->protect, 1);	/* PROTECT/ -> H */
+	usleep_range(1100, 1200);
+	gpio_set_value(panel->pdata->reset, 1);		/* LCD_RST/ -> H */
+	usleep_range(10, 100);
+	gpio_set_value(panel->pdata->protect, 0);	/* PROTECT/ -> L */
+	msleep(20);
+}
+
+/* -----------------------------------------------------------------------------
+ * Configuration
+ */
+
+static const u8 data_frame_if[] = {
+	0x02, /* WEMODE: 1=cont, 0=one-shot */
+	0x00, 0x00,
+	0x00, /* EPF, DFM */
+	0x02, /* RIM[1] : 1 (18bpp) */
+};
+
+static const u8 data_panel[] = {
+	0x0b,
+	0x63, /* 400 lines */
+	0x04, 0x00, 0x00, 0x04, 0x11, 0x00, 0x00,
+};
+
+static const u8 data_timing[] = {
+	0x00, 0x00, 0x13, 0x08, 0x08,
+};
+
+static const u8 data_timing_src[] = {
+	0x11, 0x01, 0x00, 0x01,
+};
+
+static const u8 data_gamma[] = {
+	0x01, 0x02, 0x08, 0x23,	0x03, 0x0c, 0x00, 0x06,	0x00, 0x00,
+	0x01, 0x00, 0x0c, 0x23, 0x03, 0x08, 0x02, 0x06, 0x00, 0x00,
+};
+
+static const u8 data_power[] = {
+	0x07, 0xc5, 0xdc, 0x02,	0x33, 0x0a,
+};
+
+static const u8 data_vcom[] = {
+	0x00, 0x0f, 0x02,
+};
+
+static unsigned long r61517_read_device_code(struct r61517 *panel)
+{
+	/* access protect OFF */
+	r61517_write8(panel, 0xb0, 0);
+
+	/* deep standby OFF */
+	r61517_write8(panel, 0xb1, 0);
+
+	/* device code command */
+	r61517_write_command(panel, 0xbf);
+	mdelay(50);
+
+	/* dummy read */
+	r61517_read_data(panel);
+
+	/* read device code */
+	return (r61517_read_data(panel) << 24) |
+	       (r61517_read_data(panel) << 16) |
+	       (r61517_read_data(panel) << 8) |
+	       (r61517_read_data(panel) << 0);
+}
+
+static void r61517_write_memory_start(struct r61517 *panel)
+{
+	r61517_write_command(panel, MIPI_DCS_WRITE_MEMORY_START);
+}
+
+static void r61517_clear_memory(struct r61517 *panel)
+{
+	unsigned int size = panel->pdata->mode->hactive
+			  * panel->pdata->mode->vactive;
+	unsigned int i;
+
+	r61517_write_memory_start(panel);
+
+	for (i = 0; i < size; i++)
+		r61517_write_data(panel, 0);
+}
+
+static void r61517_enable_panel(struct r61517 *panel)
+{
+	/* access protect off */
+	r61517_write8(panel, 0xb0, 0);
+
+	/* exit deep standby mode */
+	r61517_write8(panel, 0xb1, 0);
+
+	/* frame memory I/F */
+	r61517_write_array(panel, 0xb3, data_frame_if);
+
+	/* display mode and frame memory write mode */
+	r61517_write8(panel, 0xb4, 0); /* DBI, internal clock */
+
+	/* panel */
+	r61517_write_array(panel, 0xc0, data_panel);
+
+	/* timing (normal) */
+	r61517_write_array(panel, 0xc1, data_timing);
+
+	/* timing (partial) */
+	r61517_write_array(panel, 0xc2, data_timing);
+
+	/* timing (idle) */
+	r61517_write_array(panel, 0xc3, data_timing);
+
+	/* timing (source/VCOM/gate driving) */
+	r61517_write_array(panel, 0xc4, data_timing_src);
+
+	/* gamma (red) */
+	r61517_write_array(panel, 0xc8, data_gamma);
+
+	/* gamma (green) */
+	r61517_write_array(panel, 0xc9, data_gamma);
+
+	/* gamma (blue) */
+	r61517_write_array(panel, 0xca, data_gamma);
+
+	/* power (common) */
+	r61517_write_array(panel, 0xd0, data_power);
+
+	/* VCOM */
+	r61517_write_array(panel, 0xd1, data_vcom);
+
+	/* power (normal) */
+	r61517_write16(panel, 0xd2, 0x6324);
+
+	/* power (partial) */
+	r61517_write16(panel, 0xd3, 0x6324);
+
+	/* power (idle) */
+	r61517_write16(panel, 0xd4, 0x6324);
+
+	r61517_write16(panel, 0xd8, 0x7777);
+
+	/* TE signal */
+	r61517_write8(panel, MIPI_DCS_SET_TEAR_ON, 0);
+
+	/* TE signal line */
+	r61517_write16(panel, MIPI_DCS_SET_TEAR_SCANLINE, 0);
+
+	/* column address */
+	r61517_write32(panel, MIPI_DCS_SET_COLUMN_ADDRESS,
+		       panel->pdata->mode->hactive - 1);
+
+	/* page address */
+	r61517_write32(panel, MIPI_DCS_SET_PAGE_ADDRESS,
+		       panel->pdata->mode->vactive - 1);
+
+	/* exit sleep mode */
+	r61517_write_command(panel, MIPI_DCS_EXIT_SLEEP_MODE);
+
+	mdelay(120);
+
+	/* clear vram */
+	r61517_clear_memory(panel);
+}
+
+static void r61517_disable_panel(struct r61517 *panel)
+{
+	r61517_reset(panel);
+}
+
+static void r61517_display_on(struct r61517 *panel)
+{
+	r61517_write_command(panel, MIPI_DCS_SET_DISPLAY_ON);
+	mdelay(1);
+}
+
+static void r61517_display_off(struct r61517 *panel)
+{
+	r61517_write_command(panel, MIPI_DCS_SET_DISPLAY_OFF);
+}
+
+/* -----------------------------------------------------------------------------
+ * Panel operations
+ */
+
+static const struct display_entity_interface_params r61517_dbi_params = {
+	.type = DISPLAY_ENTITY_INTERFACE_DBI,
+	.p.dbi = {
+		.type = MIPI_DBI_INTERFACE_TYPE_B,
+		.flags = MIPI_DBI_INTERFACE_TE,
+		.cs_setup = 1,
+		.wr_setup = 1,
+		.wr_cycle = 9,
+		.wr_hold = 4,
+		.rd_setup = 1,
+		.rd_latch = 20,
+		.rd_cycle = 41,
+		.rd_hold = 20,
+	},
+};
+
+static int r61517_set_state(struct display_entity *entity,
+			    enum display_entity_state state)
+{
+	struct r61517 *panel = to_panel(entity);
+
+	switch (state) {
+	case DISPLAY_ENTITY_STATE_OFF:
+		r61517_disable_panel(panel);
+		break;
+
+	case DISPLAY_ENTITY_STATE_STANDBY:
+		if (entity->state == DISPLAY_ENTITY_STATE_OFF)
+			r61517_enable_panel(panel);
+		else
+			r61517_display_off(panel);
+		break;
+
+	case DISPLAY_ENTITY_STATE_ON:
+		if (entity->state == DISPLAY_ENTITY_STATE_OFF)
+			r61517_enable_panel(panel);
+
+		r61517_display_on(panel);
+		break;
+	}
+
+	return 0;
+}
+
+static int r61517_update(struct display_entity *entity)
+{
+	struct r61517 *panel = to_panel(entity);
+	struct media_pad *source;
+
+	r61517_write_memory_start(panel);
+
+	source = media_entity_remote_pad(&entity->entity.pads[0]);
+	if (source == NULL)
+		return -EPIPE;
+
+	display_entity_set_stream(to_display_entity(source->entity),
+				  source->index,
+				  DISPLAY_ENTITY_STREAM_SINGLE_SHOT);
+	return 0;
+}
+
+static int r61517_get_modes(struct display_entity *entity, unsigned int port,
+			    const struct videomode **modes)
+{
+	struct r61517 *panel = to_panel(entity);
+
+	*modes = panel->pdata->mode;
+	return 1;
+}
+
+static int r61517_get_size(struct display_entity *entity,
+			   unsigned int *width, unsigned int *height)
+{
+	struct r61517 *panel = to_panel(entity);
+
+	*width = panel->pdata->width;
+	*height = panel->pdata->height;
+	return 0;
+}
+
+static int r61517_get_params(struct display_entity *entity, unsigned int port,
+			     struct display_entity_interface_params *params)
+{
+	*params = r61517_dbi_params;
+	return 0;
+}
+
+static const struct display_entity_control_ops r61517_control_ops = {
+	.set_state = r61517_set_state,
+	.update = r61517_update,
+	.get_modes = r61517_get_modes,
+	.get_size = r61517_get_size,
+	.get_params = r61517_get_params,
+};
+
+static const struct display_entity_ops r61517_ops = {
+	.ctrl = &r61517_control_ops,
+};
+
+static int r61517_remove(struct mipi_dbi_device *dev)
+{
+	struct r61517 *panel = mipi_dbi_get_drvdata(dev);
+
+	display_entity_remove(&panel->entity);
+	display_entity_cleanup(&panel->entity);
+
+	return 0;
+}
+
+static int r61517_probe(struct mipi_dbi_device *dev)
+{
+	const struct panel_r61517_platform_data *pdata = dev->dev.platform_data;
+	struct r61517 *panel;
+	int ret;
+
+	if (pdata == NULL)
+		return -ENODEV;
+
+	panel = devm_kzalloc(&dev->dev, sizeof(*panel), GFP_KERNEL);
+	if (panel == NULL)
+		return -ENOMEM;
+
+	panel->pdata = pdata;
+	panel->dbi = dev;
+
+	dev->bus_width = pdata->bus_width;
+	mipi_dbi_set_data_width(dev, 8);
+
+	r61517_reset(panel);
+
+	if (r61517_read_device_code(panel) != 0x01221517)
+		return -ENODEV;
+
+	pr_info("R61517 panel controller detected.\n");
+
+	panel->entity.dev = &dev->dev;
+	panel->entity.ops = &r61517_ops;
+
+	ret = display_entity_init(&panel->entity, 1, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = display_entity_add(&panel->entity);
+	if (ret < 0)
+		return ret;
+
+	mipi_dbi_set_drvdata(dev, panel);
+
+	return 0;
+}
+
+static const struct dev_pm_ops r61517_dev_pm_ops = {
+};
+
+static struct mipi_dbi_device_id r61517_id_table[] = {
+	{ "panel-r61517", 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(mipi_dbi, r61517_id_table);
+
+static struct mipi_dbi_driver r61517_driver = {
+	.probe = r61517_probe,
+	.remove = r61517_remove,
+	.id_table = r61517_id_table,
+	.driver = {
+		.name = "panel-r61517",
+		.owner = THIS_MODULE,
+		.pm = &r61517_dev_pm_ops,
+	},
+};
+
+module_mipi_dbi_driver(r61517_driver);
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_DESCRIPTION("Renesas R61517-based Display Panel");
+MODULE_LICENSE("GPL");
diff --git a/include/video/panel-r61517.h b/include/video/panel-r61517.h
new file mode 100644
index 0000000..33f16af
--- /dev/null
+++ b/include/video/panel-r61517.h
@@ -0,0 +1,28 @@
+/*
+ * Renesas R61517-based Display Panels
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * 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.
+ */
+
+#ifndef __PANEL_R61517_H__
+#define __PANEL_R61517_H__
+
+struct videomode;
+
+struct panel_r61517_platform_data {
+	unsigned long width;		/* Panel width in mm */
+	unsigned long height;		/* Panel height in mm */
+	const struct videomode *mode;
+
+	unsigned int bus_width;
+	int protect;			/* Protect GPIO */
+	int reset;			/* Reset GPIO */
+};
+
+#endif /* __PANEL_R61517_H__ */
-- 
1.8.1.5

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [PATCH/RFC v3 12/19] video: display: Add VGA Digital to Analog Converter support
  2013-08-09 17:14 [PATCH/RFC v3 00/19] Common Display Framework Laurent Pinchart
                   ` (10 preceding siblings ...)
  2013-08-09 17:15 ` [PATCH/RFC v3 11/19] video: panel: Add R61517 " Laurent Pinchart
@ 2013-08-09 17:15 ` Laurent Pinchart
  2013-08-09 17:15 ` [PATCH/RFC v3 13/19] video: display: Add VGA connector support Laurent Pinchart
                   ` (9 subsequent siblings)
  21 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2013-08-09 17:15 UTC (permalink / raw)
  To: dri-devel, linux-fbdev, linux-media
  Cc: Sebastien Guiriec, Jesse Barnes, Benjamin Gaignard, Tom Gall,
	Kyungmin Park, Tomi Valkeinen, Stephen Warren, Mark Zhang,
	Stéphane Marchesin, Alexandre Courbot, Ragesh Radhakrishnan,
	Thomas Petazzoni, Sunil Joshi, Maxime Ripard, Vikas Sajjan,
	Marcus Lorentzon

This driver implements support for VGA Digital to Analog Converters
(DACs) that receive pixel data through a DPI interface and have no
control interface (GPIOs- and/or regulators-based control can be
implemented later when needed). It exposes the devices a display
entities.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/video/display/Kconfig   |   9 +++
 drivers/video/display/Makefile  |   1 +
 drivers/video/display/vga-dac.c | 152 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 162 insertions(+)
 create mode 100644 drivers/video/display/vga-dac.c

diff --git a/drivers/video/display/Kconfig b/drivers/video/display/Kconfig
index 9b44b5f..32ce08d 100644
--- a/drivers/video/display/Kconfig
+++ b/drivers/video/display/Kconfig
@@ -39,4 +39,13 @@ config DISPLAY_PANEL_R61517
 	  If you are in doubt, say N. To compile this driver as a module, choose
 	  M here; the module will be called panel-r61517.
 
+config DISPLAY_VGA_DAC
+	tristate "VGA Digital to Analog Converters"
+	---help---
+	  Support for simple VGA digital to analog converters. Those converters
+	  receive pixel data through a parallel bus and have no control bus.
+
+	  If you are in doubt, say N. To compile this driver as a module, choose
+	  M here: the module will be called vga-dac.
+
 endif # DISPLAY_CORE
diff --git a/drivers/video/display/Makefile b/drivers/video/display/Makefile
index 1cdc8d4..43cd78d 100644
--- a/drivers/video/display/Makefile
+++ b/drivers/video/display/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_DISPLAY_MIPI_DBI)			+= mipi-dbi-bus.o
 obj-$(CONFIG_DISPLAY_PANEL_DPI)			+= panel-dpi.o
 obj-$(CONFIG_DISPLAY_PANEL_R61505)		+= panel-r61505.o
 obj-$(CONFIG_DISPLAY_PANEL_R61517)		+= panel-r61517.o
+obj-$(CONFIG_DISPLAY_VGA_DAC)			+= vga-dac.o
diff --git a/drivers/video/display/vga-dac.c b/drivers/video/display/vga-dac.c
new file mode 100644
index 0000000..d0256e6
--- /dev/null
+++ b/drivers/video/display/vga-dac.c
@@ -0,0 +1,152 @@
+/*
+ * VGA Digital to Analog Converter
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <video/display.h>
+
+#define VGA_DAC_PORT_SINK		0
+#define VGA_DAC_PORT_SOURCE		1
+
+struct vga_dac {
+	struct display_entity entity;
+};
+
+static inline struct vga_dac *to_vga_dac(struct display_entity *e)
+{
+	return container_of(e, struct vga_dac, entity);
+}
+
+static int vga_dac_set_state(struct display_entity *entity,
+			     enum display_entity_state state)
+{
+	struct media_pad *source;
+
+	source = media_entity_remote_pad(&entity->entity.pads[0]);
+	if (source == NULL)
+		return -EPIPE;
+
+	switch (state) {
+	case DISPLAY_ENTITY_STATE_OFF:
+	case DISPLAY_ENTITY_STATE_STANDBY:
+		display_entity_set_stream(to_display_entity(source->entity),
+					  source->index,
+					  DISPLAY_ENTITY_STREAM_STOPPED);
+		break;
+
+	case DISPLAY_ENTITY_STATE_ON:
+		display_entity_set_stream(to_display_entity(source->entity),
+					  source->index,
+					  DISPLAY_ENTITY_STREAM_CONTINUOUS);
+		break;
+	}
+
+	return 0;
+}
+
+static int vga_dac_get_params(struct display_entity *entity, unsigned int port,
+			      struct display_entity_interface_params *params)
+{
+	memset(params, 0, sizeof(*params));
+
+	if (port == VGA_DAC_PORT_SINK)
+		params->type = DISPLAY_ENTITY_INTERFACE_DPI;
+	else
+		params->type = DISPLAY_ENTITY_INTERFACE_VGA;
+
+	return 0;
+}
+
+static const struct display_entity_control_ops vga_dac_control_ops = {
+	.set_state = vga_dac_set_state,
+	.get_params = vga_dac_get_params,
+};
+
+static const struct display_entity_ops vga_dac_ops = {
+	.ctrl = &vga_dac_control_ops,
+};
+
+static int vga_dac_remove(struct platform_device *pdev)
+{
+	struct vga_dac *dac = platform_get_drvdata(pdev);
+
+	display_entity_remove(&dac->entity);
+	display_entity_cleanup(&dac->entity);
+
+	return 0;
+}
+
+static int vga_dac_probe(struct platform_device *pdev)
+{
+	struct vga_dac *dac;
+	int ret;
+
+	dac = devm_kzalloc(&pdev->dev, sizeof(*dac), GFP_KERNEL);
+	if (dac == NULL)
+		return -ENOMEM;
+
+	dac->entity.dev = &pdev->dev;
+	dac->entity.ops = &vga_dac_ops;
+	strlcpy(dac->entity.name, dev_name(&pdev->dev),
+		sizeof(dac->entity.name));
+
+	ret = display_entity_init(&dac->entity, 1, 1);
+	if (ret < 0)
+		return ret;
+
+	ret = display_entity_add(&dac->entity);
+	if (ret < 0)
+		return ret;
+
+	platform_set_drvdata(pdev, dac);
+
+	return 0;
+}
+
+static const struct dev_pm_ops vga_dac_dev_pm_ops = {
+};
+
+static struct platform_device_id vga_dac_id_table[] = {
+	{ "adv7123", 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(platform, vga_dac_id_table);
+
+#ifdef CONFIG_OF
+static struct of_device_id vga_dac_of_id_table[] = {
+	{ .compatible = "adi,adv7123", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, vga_dac_of_id_table);
+#endif
+
+static struct platform_driver vga_dac_driver = {
+	.probe = vga_dac_probe,
+	.remove = vga_dac_remove,
+	.id_table = vga_dac_id_table,
+	.driver = {
+		.name = "vga-dac",
+		.owner = THIS_MODULE,
+		.pm = &vga_dac_dev_pm_ops,
+		.of_match_table = of_match_ptr(vga_dac_of_id_table),
+	},
+};
+
+module_platform_driver(vga_dac_driver);
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_DESCRIPTION("VGA Digital-to-Analog Converter");
+MODULE_LICENSE("GPL");
-- 
1.8.1.5

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [PATCH/RFC v3 13/19] video: display: Add VGA connector support
  2013-08-09 17:14 [PATCH/RFC v3 00/19] Common Display Framework Laurent Pinchart
                   ` (11 preceding siblings ...)
  2013-08-09 17:15 ` [PATCH/RFC v3 12/19] video: display: Add VGA Digital to Analog Converter support Laurent Pinchart
@ 2013-08-09 17:15 ` Laurent Pinchart
  2013-08-09 17:15 ` [PATCH/RFC v3 14/19] ARM: shmobile: r8a7790: Add DU clocks for DT Laurent Pinchart
                   ` (8 subsequent siblings)
  21 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2013-08-09 17:15 UTC (permalink / raw)
  To: dri-devel, linux-fbdev, linux-media
  Cc: Sebastien Guiriec, Jesse Barnes, Benjamin Gaignard, Tom Gall,
	Kyungmin Park, Tomi Valkeinen, Stephen Warren, Mark Zhang,
	Stéphane Marchesin, Alexandre Courbot, Ragesh Radhakrishnan,
	Thomas Petazzoni, Sunil Joshi, Maxime Ripard, Vikas Sajjan,
	Marcus Lorentzon

This driver exposes VGA connectors as display entity devices. The
connectors are passive devices that pass analog VGA signals though. They
optionally cary DDC signals for bidirectional control communications
with the devices connected to the connectors.

EDID retrieval isn't supported yet.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/video/display/Kconfig   |  11 +++
 drivers/video/display/Makefile  |   1 +
 drivers/video/display/con-vga.c | 148 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 160 insertions(+)
 create mode 100644 drivers/video/display/con-vga.c

diff --git a/drivers/video/display/Kconfig b/drivers/video/display/Kconfig
index 32ce08d..9b482a8 100644
--- a/drivers/video/display/Kconfig
+++ b/drivers/video/display/Kconfig
@@ -5,6 +5,17 @@ menuconfig DISPLAY_CORE
 
 if DISPLAY_CORE
 
+
+config DISPLAY_CONNECTOR_VGA
+	tristate "VGA Connector"
+	---help---
+	  Support for simple digital (parallel) pixel interface panels. Those
+	  panels receive pixel data through a parallel bus and have no control
+	  bus.
+
+	  If you are in doubt, say N. To compile this driver as a module, choose
+	  M here; the module will be called con-vga.
+
 config DISPLAY_MIPI_DBI
 	tristate
 	default n
diff --git a/drivers/video/display/Makefile b/drivers/video/display/Makefile
index 43cd78d..d03c64a 100644
--- a/drivers/video/display/Makefile
+++ b/drivers/video/display/Makefile
@@ -1,6 +1,7 @@
 display-y					:= display-core.o \
 						   display-notifier.o
 obj-$(CONFIG_DISPLAY_CORE)			+= display.o
+obj-$(CONFIG_DISPLAY_CONNECTOR_VGA)		+= con-vga.o
 obj-$(CONFIG_DISPLAY_MIPI_DBI)			+= mipi-dbi-bus.o
 obj-$(CONFIG_DISPLAY_PANEL_DPI)			+= panel-dpi.o
 obj-$(CONFIG_DISPLAY_PANEL_R61505)		+= panel-r61505.o
diff --git a/drivers/video/display/con-vga.c b/drivers/video/display/con-vga.c
new file mode 100644
index 0000000..798ac9e
--- /dev/null
+++ b/drivers/video/display/con-vga.c
@@ -0,0 +1,148 @@
+/*
+ * VGA Connector
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <video/display.h>
+
+struct con_vga {
+	struct display_entity entity;
+};
+
+static int con_vga_set_state(struct display_entity *entity,
+			     enum display_entity_state state)
+{
+	struct media_pad *source;
+
+	source = media_entity_remote_pad(&entity->entity.pads[0]);
+	if (source == NULL)
+		return -EPIPE;
+
+	switch (state) {
+	case DISPLAY_ENTITY_STATE_OFF:
+	case DISPLAY_ENTITY_STATE_STANDBY:
+		display_entity_set_stream(to_display_entity(source->entity),
+					  source->index,
+					  DISPLAY_ENTITY_STREAM_STOPPED);
+		break;
+
+	case DISPLAY_ENTITY_STATE_ON:
+		display_entity_set_stream(to_display_entity(source->entity),
+					  source->index,
+					  DISPLAY_ENTITY_STREAM_CONTINUOUS);
+		break;
+	}
+
+	return 0;
+}
+
+static int con_vga_get_modes(struct display_entity *entity, unsigned int port,
+			     const struct videomode **modes)
+{
+	/* TODO: Add EDID retrieval support. */
+	return 0;
+}
+
+static int con_vga_get_params(struct display_entity *entity, unsigned int port,
+			      struct display_entity_interface_params *params)
+{
+	memset(params, 0, sizeof(*params));
+
+	params->type = DISPLAY_ENTITY_INTERFACE_VGA;
+
+	return 0;
+}
+
+static const struct display_entity_control_ops con_vga_control_ops = {
+	.set_state = con_vga_set_state,
+	.get_modes = con_vga_get_modes,
+	.get_params = con_vga_get_params,
+};
+
+static const struct display_entity_ops con_vga_ops = {
+	.ctrl = &con_vga_control_ops,
+};
+
+static int con_vga_remove(struct platform_device *pdev)
+{
+	struct con_vga *con = platform_get_drvdata(pdev);
+
+	display_entity_remove(&con->entity);
+	display_entity_cleanup(&con->entity);
+
+	return 0;
+}
+
+static int con_vga_probe(struct platform_device *pdev)
+{
+	struct con_vga *con;
+	int ret;
+
+	con = devm_kzalloc(&pdev->dev, sizeof(*con), GFP_KERNEL);
+	if (con == NULL)
+		return -ENOMEM;
+
+	con->entity.dev = &pdev->dev;
+	con->entity.ops = &con_vga_ops;
+	strlcpy(con->entity.name, "vga-con", sizeof(con->entity.name));
+
+	ret = display_entity_init(&con->entity, 1, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = display_entity_add(&con->entity);
+	if (ret < 0)
+		return ret;
+
+	platform_set_drvdata(pdev, con);
+
+	return 0;
+}
+
+static const struct dev_pm_ops con_vga_dev_pm_ops = {
+};
+
+static struct platform_device_id con_vga_id_table[] = {
+	{ "con-vga", 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(platform, con_vga_id_table);
+
+#ifdef CONFIG_OF
+static struct of_device_id con_vga_of_id_table[] = {
+	{ .compatible = "con-vga", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, con_vga_of_id_table);
+#endif
+
+static struct platform_driver con_vga_driver = {
+	.probe = con_vga_probe,
+	.remove = con_vga_remove,
+	.id_table = con_vga_id_table,
+	.driver = {
+		.name = "con-vga",
+		.owner = THIS_MODULE,
+		.pm = &con_vga_dev_pm_ops,
+		.of_match_table = of_match_ptr(con_vga_of_id_table),
+	},
+};
+
+module_platform_driver(con_vga_driver);
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_DESCRIPTION("VGA Connector");
+MODULE_LICENSE("GPL");
-- 
1.8.1.5

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [PATCH/RFC v3 14/19] ARM: shmobile: r8a7790: Add DU clocks for DT
  2013-08-09 17:14 [PATCH/RFC v3 00/19] Common Display Framework Laurent Pinchart
                   ` (12 preceding siblings ...)
  2013-08-09 17:15 ` [PATCH/RFC v3 13/19] video: display: Add VGA connector support Laurent Pinchart
@ 2013-08-09 17:15 ` Laurent Pinchart
  2013-08-09 17:15 ` [PATCH/RFC v3 15/19] ARM: shmobile: r8a7790: Add DU device node to device tree Laurent Pinchart
                   ` (7 subsequent siblings)
  21 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2013-08-09 17:15 UTC (permalink / raw)
  To: dri-devel, linux-fbdev, linux-media
  Cc: Sebastien Guiriec, Jesse Barnes, Benjamin Gaignard, Tom Gall,
	Kyungmin Park, Tomi Valkeinen, Stephen Warren, Mark Zhang,
	Stéphane Marchesin, Alexandre Courbot, Ragesh Radhakrishnan,
	Thomas Petazzoni, Sunil Joshi, Maxime Ripard, Vikas Sajjan,
	Marcus Lorentzon

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 arch/arm/mach-shmobile/clock-r8a7790.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/mach-shmobile/clock-r8a7790.c b/arch/arm/mach-shmobile/clock-r8a7790.c
index d99b87b..7229f96 100644
--- a/arch/arm/mach-shmobile/clock-r8a7790.c
+++ b/arch/arm/mach-shmobile/clock-r8a7790.c
@@ -257,10 +257,15 @@ static struct clk_lookup lookups[] = {
 
 	/* MSTP */
 	CLKDEV_ICK_ID("lvds.0", "rcar-du-r8a7790", &mstp_clks[MSTP726]),
+	CLKDEV_ICK_ID("lvds.0", "feb00000.display", &mstp_clks[MSTP726]),
 	CLKDEV_ICK_ID("lvds.1", "rcar-du-r8a7790", &mstp_clks[MSTP725]),
+	CLKDEV_ICK_ID("lvds.1", "feb00000.display", &mstp_clks[MSTP725]),
 	CLKDEV_ICK_ID("du.0", "rcar-du-r8a7790", &mstp_clks[MSTP724]),
+	CLKDEV_ICK_ID("du.0", "feb00000.display", &mstp_clks[MSTP724]),
 	CLKDEV_ICK_ID("du.1", "rcar-du-r8a7790", &mstp_clks[MSTP723]),
+	CLKDEV_ICK_ID("du.1", "feb00000.display", &mstp_clks[MSTP723]),
 	CLKDEV_ICK_ID("du.2", "rcar-du-r8a7790", &mstp_clks[MSTP722]),
+	CLKDEV_ICK_ID("du.2", "feb00000.display", &mstp_clks[MSTP722]),
 	CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]),
 	CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]),
 	CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[MSTP206]),
-- 
1.8.1.5

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [PATCH/RFC v3 15/19] ARM: shmobile: r8a7790: Add DU device node to device tree
  2013-08-09 17:14 [PATCH/RFC v3 00/19] Common Display Framework Laurent Pinchart
                   ` (13 preceding siblings ...)
  2013-08-09 17:15 ` [PATCH/RFC v3 14/19] ARM: shmobile: r8a7790: Add DU clocks for DT Laurent Pinchart
@ 2013-08-09 17:15 ` Laurent Pinchart
  2013-08-09 17:15 ` [PATCH/RFC v3 16/19] ARM: shmobile: marzen: Port DU platform data to CDF Laurent Pinchart
                   ` (6 subsequent siblings)
  21 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2013-08-09 17:15 UTC (permalink / raw)
  To: dri-devel, linux-fbdev, linux-media
  Cc: Sebastien Guiriec, Jesse Barnes, Benjamin Gaignard, Tom Gall,
	Kyungmin Park, Tomi Valkeinen, Stephen Warren, Mark Zhang,
	Stéphane Marchesin, Alexandre Courbot, Ragesh Radhakrishnan,
	Thomas Petazzoni, Sunil Joshi, Maxime Ripard, Vikas Sajjan,
	Marcus Lorentzon

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 arch/arm/boot/dts/r8a7790.dtsi | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index ab0582c..b63f1a6 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -186,4 +186,37 @@
 		reg = <0 0xe6060000 0 0x250>;
 		#gpio-range-cells = <3>;
 	};
+
+	du: display@feb00000 {
+		compatible = "renesas,du-r8a7790";
+		reg = <0 0xfeb00000 0 0x70000>,
+		      <0 0xfeb90000 0 0x1c>,
+		      <0 0xfeb94000 0 0x1c>;
+		reg-names = "core", "lvds.0", "lvds.1";
+		interrupt-parent = <&gic>;
+		interrupts = <0 256 4
+			      0 268 4
+			      0 269 4>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				du_out_rgb: endpoint {
+				};
+			};
+			port@1 {
+				reg = <1>;
+				du_out_lvds0: endpoint {
+				};
+			};
+			port@2 {
+				reg = <2>;
+				du_out_lvds1: endpoint {
+				};
+			};
+		};
+	};
 };
-- 
1.8.1.5

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [PATCH/RFC v3 16/19] ARM: shmobile: marzen: Port DU platform data to CDF
  2013-08-09 17:14 [PATCH/RFC v3 00/19] Common Display Framework Laurent Pinchart
                   ` (14 preceding siblings ...)
  2013-08-09 17:15 ` [PATCH/RFC v3 15/19] ARM: shmobile: r8a7790: Add DU device node to device tree Laurent Pinchart
@ 2013-08-09 17:15 ` Laurent Pinchart
  2013-08-09 17:15 ` [PATCH/RFC v3 17/19] ARM: shmobile: lager: " Laurent Pinchart
                   ` (5 subsequent siblings)
  21 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2013-08-09 17:15 UTC (permalink / raw)
  To: dri-devel, linux-fbdev, linux-media
  Cc: Sebastien Guiriec, Jesse Barnes, Benjamin Gaignard, Tom Gall,
	Kyungmin Park, Tomi Valkeinen, Stephen Warren, Mark Zhang,
	Stéphane Marchesin, Alexandre Courbot, Ragesh Radhakrishnan,
	Thomas Petazzoni, Sunil Joshi, Maxime Ripard, Vikas Sajjan,
	Marcus Lorentzon

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 arch/arm/mach-shmobile/board-marzen.c | 77 ++++++++++++++++++++++++-----------
 1 file changed, 53 insertions(+), 24 deletions(-)

diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c
index 6499f1a..be1b7cb 100644
--- a/arch/arm/mach-shmobile/board-marzen.c
+++ b/arch/arm/mach-shmobile/board-marzen.c
@@ -39,6 +39,8 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mfd/tmio.h>
+#include <video/panel-dpi.h>
+#include <video/videomode.h>
 #include <mach/r8a7779.h>
 #include <mach/common.h>
 #include <mach/irqs.h>
@@ -174,35 +176,56 @@ static struct platform_device hspi_device = {
  * The panel only specifies the [hv]display and [hv]total values. The position
  * and width of the sync pulses don't matter, they're copied from VESA timings.
  */
-static struct rcar_du_encoder_data du_encoders[] = {
+static const struct videomode marzen_panel_mode = {
+	.pixelclock = 65000000,
+	.hactive = 1024,
+	.hfront_porch = 24,
+	.hback_porch = 160,
+	.hsync_len = 136,
+	.vactive = 768,
+	.vfront_porch = 3,
+	.vback_porch = 29,
+	.vsync_len = 6,
+	.flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW,
+};
+
+static const struct panel_dpi_platform_data marzen_panel_data = {
+	.width = 210,
+	.height = 158,
+	.mode = &marzen_panel_mode,
+};
+
+static const struct display_entity_graph_data marzen_du_entities[] = {
 	{
-		.type = RCAR_DU_ENCODER_VGA,
-		.output = RCAR_DU_OUTPUT_DPAD0,
+		.name = "adv7123",
+		.sources = (const struct display_entity_source_data[]) {
+			{
+				.name = "rcar-du",
+				.port = 0,
+			},
+		},
 	}, {
-		.type = RCAR_DU_ENCODER_LVDS,
-		.output = RCAR_DU_OUTPUT_DPAD1,
-		.connector.lvds.panel = {
-			.width_mm = 210,
-			.height_mm = 158,
-			.mode = {
-				.clock = 65000,
-				.hdisplay = 1024,
-				.hsync_start = 1048,
-				.hsync_end = 1184,
-				.htotal = 1344,
-				.vdisplay = 768,
-				.vsync_start = 771,
-				.vsync_end = 777,
-				.vtotal = 806,
-				.flags = 0,
+		.name = "con-vga",
+		.sources = (const struct display_entity_source_data[]) {
+			{
+				.name = "adv7123",
+				.port = 1,
 			},
 		},
+	}, {
+		.name = "panel-dpi",
+		.sources = (const struct display_entity_source_data[]) {
+			{
+				.name = "rcar-du",
+				.port = 1,
+			},
+		},
+	}, {
 	},
 };
 
-static const struct rcar_du_platform_data du_pdata __initconst = {
-	.encoders = du_encoders,
-	.num_encoders = ARRAY_SIZE(du_encoders),
+static const struct rcar_du_platform_data marzen_du_pdata __initconst = {
+	.graph = marzen_du_entities,
 };
 
 static const struct resource du_resources[] __initconst = {
@@ -217,8 +240,8 @@ static void __init marzen_add_du_device(void)
 		.id = -1,
 		.res = du_resources,
 		.num_res = ARRAY_SIZE(du_resources),
-		.data = &du_pdata,
-		.size_data = sizeof(du_pdata),
+		.data = &marzen_du_pdata,
+		.size_data = sizeof(marzen_du_pdata),
 		.dma_mask = DMA_BIT_MASK(32),
 	};
 
@@ -327,6 +350,12 @@ static void __init marzen_init(void)
 	r8a7779_add_standard_devices();
 	platform_add_devices(marzen_devices, ARRAY_SIZE(marzen_devices));
 	marzen_add_du_device();
+
+	platform_device_register_simple("adv7123", -1, NULL, 0);
+	platform_device_register_simple("con-vga", -1, NULL, 0);
+	platform_device_register_data(&platform_bus, "panel-dpi", -1,
+				      &marzen_panel_data,
+				      sizeof(marzen_panel_data));
 }
 
 static const char *marzen_boards_compat_dt[] __initdata = {
-- 
1.8.1.5

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [PATCH/RFC v3 17/19] ARM: shmobile: lager: Port DU platform data to CDF
  2013-08-09 17:14 [PATCH/RFC v3 00/19] Common Display Framework Laurent Pinchart
                   ` (15 preceding siblings ...)
  2013-08-09 17:15 ` [PATCH/RFC v3 16/19] ARM: shmobile: marzen: Port DU platform data to CDF Laurent Pinchart
@ 2013-08-09 17:15 ` Laurent Pinchart
  2013-08-09 17:15 ` [PATCH/RFC v3 18/19] ARM: shmobile: lager-reference: Add display device nodes to device tree Laurent Pinchart
                   ` (4 subsequent siblings)
  21 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2013-08-09 17:15 UTC (permalink / raw)
  To: dri-devel, linux-fbdev, linux-media
  Cc: Sebastien Guiriec, Jesse Barnes, Benjamin Gaignard, Tom Gall,
	Kyungmin Park, Tomi Valkeinen, Stephen Warren, Mark Zhang,
	Stéphane Marchesin, Alexandre Courbot, Ragesh Radhakrishnan,
	Thomas Petazzoni, Sunil Joshi, Maxime Ripard, Vikas Sajjan,
	Marcus Lorentzon

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 arch/arm/mach-shmobile/board-lager.c | 76 +++++++++++++++++++++++++-----------
 1 file changed, 53 insertions(+), 23 deletions(-)

diff --git a/arch/arm/mach-shmobile/board-lager.c b/arch/arm/mach-shmobile/board-lager.c
index 75a01bc..d61b892 100644
--- a/arch/arm/mach-shmobile/board-lager.c
+++ b/arch/arm/mach-shmobile/board-lager.c
@@ -33,6 +33,8 @@
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 #include <linux/sh_eth.h>
+#include <video/panel-dpi.h>
+#include <video/videomode.h>
 #include <mach/common.h>
 #include <mach/irqs.h>
 #include <mach/r8a7790.h>
@@ -40,35 +42,56 @@
 #include <asm/mach/arch.h>
 
 /* DU */
-static struct rcar_du_encoder_data lager_du_encoders[] = {
+static const struct videomode lager_panel_mode = {
+	.pixelclock = 65000000,
+	.hactive = 1024,
+	.hfront_porch = 24,
+	.hback_porch = 160,
+	.hsync_len = 136,
+	.vactive = 768,
+	.vfront_porch = 3,
+	.vback_porch = 29,
+	.vsync_len = 6,
+	.flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW,
+};
+
+static const struct panel_dpi_platform_data lager_panel_data = {
+	.width = 210,
+	.height = 158,
+	.mode = &lager_panel_mode,
+};
+
+static const struct display_entity_graph_data lager_du_entities[] = {
 	{
-		.type = RCAR_DU_ENCODER_VGA,
-		.output = RCAR_DU_OUTPUT_DPAD0,
+		.name = "adv7123",
+		.sources = (const struct display_entity_source_data[]) {
+			{
+				.name = "rcar-du",
+				.port = 0,
+			},
+		},
 	}, {
-		.type = RCAR_DU_ENCODER_NONE,
-		.output = RCAR_DU_OUTPUT_LVDS1,
-		.connector.lvds.panel = {
-			.width_mm = 210,
-			.height_mm = 158,
-			.mode = {
-				.clock = 65000,
-				.hdisplay = 1024,
-				.hsync_start = 1048,
-				.hsync_end = 1184,
-				.htotal = 1344,
-				.vdisplay = 768,
-				.vsync_start = 771,
-				.vsync_end = 777,
-				.vtotal = 806,
-				.flags = 0,
+		.name = "con-vga",
+		.sources = (const struct display_entity_source_data[]) {
+			{
+				.name = "adv7123",
+				.port = 1,
 			},
 		},
+	}, {
+		.name = "panel-dpi",
+		.sources = (const struct display_entity_source_data[]) {
+			{
+				.name = "rcar-du",
+				.port = 2,
+			},
+		},
+	}, {
 	},
 };
 
 static const struct rcar_du_platform_data lager_du_pdata __initconst = {
-	.encoders = lager_du_encoders,
-	.num_encoders = ARRAY_SIZE(lager_du_encoders),
+	.graph = lager_du_entities,
 };
 
 static const struct resource du_resources[] __initconst = {
@@ -87,8 +110,8 @@ static void __init lager_add_du_device(void)
 		.id = -1,
 		.res = du_resources,
 		.num_res = ARRAY_SIZE(du_resources),
-		.data = &du_resources,
-		.size_data = sizeof(du_resources),
+		.data = &lager_du_pdata,
+		.size_data = sizeof(lager_du_pdata),
 		.dma_mask = DMA_BIT_MASK(32),
 	};
 
@@ -202,6 +225,7 @@ static void __init lager_add_standard_devices(void)
 	r8a7790_pinmux_init();
 
 	r8a7790_add_standard_devices();
+
 	platform_device_register_data(&platform_bus, "leds-gpio", -1,
 				      &lager_leds_pdata,
 				      sizeof(lager_leds_pdata));
@@ -220,6 +244,12 @@ static void __init lager_add_standard_devices(void)
 					  &ether_pdata, sizeof(ether_pdata));
 
 	lager_add_du_device();
+
+	platform_device_register_simple("adv7123", -1, NULL, 0);
+	platform_device_register_simple("con-vga", -1, NULL, 0);
+	platform_device_register_data(&platform_bus, "panel-dpi", -1,
+				      &lager_panel_data,
+				      sizeof(lager_panel_data));
 }
 
 static const char * const lager_boards_compat_dt[] __initconst = {
-- 
1.8.1.5

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [PATCH/RFC v3 18/19] ARM: shmobile: lager-reference: Add display device nodes to device tree
  2013-08-09 17:14 [PATCH/RFC v3 00/19] Common Display Framework Laurent Pinchart
                   ` (16 preceding siblings ...)
  2013-08-09 17:15 ` [PATCH/RFC v3 17/19] ARM: shmobile: lager: " Laurent Pinchart
@ 2013-08-09 17:15 ` Laurent Pinchart
  2013-08-09 17:15 ` [PATCH/RFC v3 19/19] drm/rcar-du: Port to the Common Display Framework Laurent Pinchart
                   ` (3 subsequent siblings)
  21 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2013-08-09 17:15 UTC (permalink / raw)
  To: dri-devel, linux-fbdev, linux-media
  Cc: Sebastien Guiriec, Jesse Barnes, Benjamin Gaignard, Tom Gall,
	Kyungmin Park, Tomi Valkeinen, Stephen Warren, Mark Zhang,
	Stéphane Marchesin, Alexandre Courbot, Ragesh Radhakrishnan,
	Thomas Petazzoni, Sunil Joshi, Maxime Ripard, Vikas Sajjan,
	Marcus Lorentzon

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 arch/arm/boot/dts/r8a7790-lager-reference.dts | 92 +++++++++++++++++++++++++++
 1 file changed, 92 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7790-lager-reference.dts b/arch/arm/boot/dts/r8a7790-lager-reference.dts
index d9a25d5..ba2469b 100644
--- a/arch/arm/boot/dts/r8a7790-lager-reference.dts
+++ b/arch/arm/boot/dts/r8a7790-lager-reference.dts
@@ -42,6 +42,98 @@
 			gpios = <&gpio5 17 GPIO_ACTIVE_HIGH>;
 		};
 	};
+
+	adv7123 {
+		compatible = "adi,adv7123";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				adv7123_in: endpoint {
+					remote-endpoint = <&du_out_rgb>;
+				};
+			};
+			port@1 {
+				reg = <1>;
+				adv7123_out: endpoint {
+					remote-endpoint = <&con_vga_in>;
+				};
+			};
+		};
+	};
+
+	con-vga {
+		compatible = "con-vga";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				con_vga_in: endpoint {
+					remote-endpoint = <&adv7123_out>;
+				};
+			};
+		};
+	};
+
+	panel-dpi {
+		compatible = "panel-dpi";
+
+		width-mm = <210>;
+		height-mm = <158>;
+
+		display-timings {
+			timing {
+				/* 1024x768 @65Hz */
+				clock-frequency = <65000000>;
+				hactive = <1024>;
+				vactive = <768>;
+				hsync-len = <136>;
+				hfront-porch = <20>;
+				hback-porch = <160>;
+				vfront-porch = <3>;
+				vback-porch = <29>;
+				vsync-len = <6>;
+			};
+		};
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				panel_in: endpoint {
+					remote-endpoint = <&du_out_lvds1>;
+				};
+			};
+		};
+	};
+};
+
+&du {
+	pinctrl-0 = <&du_pins>;
+	pinctrl-names = "default";
+};
+
+&du_out_rgb {
+	remote-endpoint = <&adv7123_in>;
+};
+
+&du_out_lvds1 {
+	remote-endpoint = <&panel_in>;
+};
+
+&pfc {
+	du_pins: du {
+		renesas,groups = "du_rgb666", "du_sync_1", "du_clk_out_0";
+		renesas,function = "du";
+	};
 };
 
 &pfc {
-- 
1.8.1.5

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [PATCH/RFC v3 19/19] drm/rcar-du: Port to the Common Display Framework
  2013-08-09 17:14 [PATCH/RFC v3 00/19] Common Display Framework Laurent Pinchart
                   ` (17 preceding siblings ...)
  2013-08-09 17:15 ` [PATCH/RFC v3 18/19] ARM: shmobile: lager-reference: Add display device nodes to device tree Laurent Pinchart
@ 2013-08-09 17:15 ` Laurent Pinchart
  2013-08-14  0:43 ` [PATCH/RFC v3 00/19] " Rob Clark
                   ` (2 subsequent siblings)
  21 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2013-08-09 17:15 UTC (permalink / raw)
  To: dri-devel, linux-fbdev, linux-media
  Cc: Sebastien Guiriec, Jesse Barnes, Benjamin Gaignard, Tom Gall,
	Kyungmin Park, Tomi Valkeinen, Stephen Warren, Mark Zhang,
	Stéphane Marchesin, Alexandre Courbot, Ragesh Radhakrishnan,
	Thomas Petazzoni, Sunil Joshi, Maxime Ripard, Vikas Sajjan,
	Marcus Lorentzon

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/rcar-du/Kconfig             |   3 +-
 drivers/gpu/drm/rcar-du/Makefile            |   7 +-
 drivers/gpu/drm/rcar-du/rcar_du_connector.c | 164 ++++++++++++++++
 drivers/gpu/drm/rcar-du/rcar_du_connector.h |  36 ++++
 drivers/gpu/drm/rcar-du/rcar_du_crtc.h      |   2 +-
 drivers/gpu/drm/rcar-du/rcar_du_drv.c       | 279 ++++++++++++++++++++++++----
 drivers/gpu/drm/rcar-du/rcar_du_drv.h       |  28 ++-
 drivers/gpu/drm/rcar-du/rcar_du_encoder.c   |  87 ++++-----
 drivers/gpu/drm/rcar-du/rcar_du_encoder.h   |  22 +--
 drivers/gpu/drm/rcar-du/rcar_du_kms.c       | 116 ++++++++++--
 drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c   | 131 -------------
 drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h   |  25 ---
 drivers/gpu/drm/rcar-du/rcar_du_vgacon.c    |  96 ----------
 drivers/gpu/drm/rcar-du/rcar_du_vgacon.h    |  23 ---
 include/linux/platform_data/rcar-du.h       |  55 +-----
 15 files changed, 611 insertions(+), 463 deletions(-)
 create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_connector.c
 create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_connector.h
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
 delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_lvdscon.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 c590cd9..a54eeba 100644
--- a/drivers/gpu/drm/rcar-du/Kconfig
+++ b/drivers/gpu/drm/rcar-du/Kconfig
@@ -1,9 +1,10 @@
 config DRM_RCAR_DU
 	tristate "DRM Support for R-Car Display Unit"
-	depends on DRM && ARM
+	depends on DRM && ARM && OF
 	select DRM_KMS_HELPER
 	select DRM_KMS_CMA_HELPER
 	select DRM_GEM_CMA_HELPER
+	select VIDEOMODE_HELPERS
 	help
 	  Choose this option if you have an R-Car chipset.
 	  If M is selected the module will be called rcar-du-drm.
diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile
index 12b8d44..3ac8566 100644
--- a/drivers/gpu/drm/rcar-du/Makefile
+++ b/drivers/gpu/drm/rcar-du/Makefile
@@ -1,11 +1,10 @@
-rcar-du-drm-y := rcar_du_crtc.o \
+rcar-du-drm-y := rcar_du_connector.o \
+		 rcar_du_crtc.o \
 		 rcar_du_drv.o \
 		 rcar_du_encoder.o \
 		 rcar_du_group.o \
 		 rcar_du_kms.o \
-		 rcar_du_lvdscon.o \
-		 rcar_du_plane.o \
-		 rcar_du_vgacon.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_connector.c b/drivers/gpu/drm/rcar-du/rcar_du_connector.c
new file mode 100644
index 0000000..a09aada
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rcar_du_connector.c
@@ -0,0 +1,164 @@
+/*
+ * rcar_du_connector.c  --  R-Car Display Unit Connector
+ *
+ * Copyright (C) 2013 Renesas Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@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 <linux/export.h>
+#include <video/videomode.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+
+#include "rcar_du_drv.h"
+#include "rcar_du_connector.h"
+#include "rcar_du_encoder.h"
+#include "rcar_du_kms.h"
+
+static int rcar_du_connector_get_modes(struct drm_connector *connector)
+{
+	struct rcar_du_connector *rcon = to_rcar_connector(connector);
+	struct display_entity *entity = to_display_entity(rcon->pad->entity);
+	const struct videomode *modes;
+	int ret;
+	int i;
+
+	ret = display_entity_get_modes(entity, rcon->pad->index, &modes);
+	if (ret <= 0)
+		return drm_add_modes_noedid(connector, 1280, 768);
+
+	for (i = 0; i < ret; ++i) {
+		struct drm_display_mode *mode;
+
+		mode = drm_mode_create(connector->dev);
+		if (mode == NULL)
+			break;
+
+		mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
+		drm_display_mode_from_videomode(&modes[i], mode);
+		drm_mode_probed_add(connector, mode);
+	}
+
+	return i;
+}
+
+static int rcar_du_connector_mode_valid(struct drm_connector *connector,
+					struct drm_display_mode *mode)
+{
+	return MODE_OK;
+}
+
+static struct drm_encoder *
+rcar_du_connector_best_encoder(struct drm_connector *connector)
+{
+	struct rcar_du_connector *rcon = to_rcar_connector(connector);
+
+	return &rcon->encoder->encoder;
+}
+
+static const struct drm_connector_helper_funcs connector_helper_funcs = {
+	.get_modes = rcar_du_connector_get_modes,
+	.mode_valid = rcar_du_connector_mode_valid,
+	.best_encoder = rcar_du_connector_best_encoder,
+};
+
+static void rcar_du_connector_destroy(struct drm_connector *connector)
+{
+	drm_sysfs_connector_remove(connector);
+	drm_connector_cleanup(connector);
+}
+
+static enum drm_connector_status
+rcar_du_connector_detect(struct drm_connector *connector, bool force)
+{
+	return connector_status_connected;
+}
+
+static const struct drm_connector_funcs connector_funcs = {
+	.dpms = drm_helper_connector_dpms,
+	.detect = rcar_du_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = rcar_du_connector_destroy,
+};
+
+struct rcar_du_connector *
+rcar_du_connector_create(struct rcar_du_device *rcdu,
+			 struct rcar_du_encoder *renc, struct media_pad *pad)
+{
+	struct display_entity *entity = to_display_entity(pad->entity);
+	struct display_entity_interface_params params;
+	struct rcar_du_connector *rcon;
+	struct drm_connector *connector;
+	int connector_type;
+	unsigned int width;
+	unsigned int height;
+	int ret;
+
+	rcon = devm_kzalloc(rcdu->dev, sizeof(*rcon), GFP_KERNEL);
+	if (rcon == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	rcon->encoder = renc;
+	rcon->pad = pad;
+
+	connector = &rcon->connector;
+
+	ret = display_entity_get_size(entity, &width, &height);
+	if (ret < 0) {
+		connector->display_info.width_mm = 0;
+		connector->display_info.height_mm = 0;
+	} else {
+		connector->display_info.width_mm = width;
+		connector->display_info.height_mm = height;
+	}
+
+	ret = display_entity_get_params(entity, pad->index, &params);
+	if (ret < 0) {
+		dev_dbg(rcdu->dev,
+			"failed to retrieve connector %s parameters\n",
+			entity->name);
+		return ERR_PTR(ret);
+	}
+
+	switch (params.type) {
+	case DISPLAY_ENTITY_INTERFACE_VGA:
+		connector_type = DRM_MODE_CONNECTOR_VGA;
+		break;
+	case DISPLAY_ENTITY_INTERFACE_LVDS:
+		connector_type = DRM_MODE_CONNECTOR_LVDS;
+		break;
+	default:
+		connector_type = DRM_MODE_CONNECTOR_Unknown;
+		break;
+	}
+
+	ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs,
+				 connector_type);
+	if (ret < 0)
+		return ERR_PTR(ret);
+
+	drm_connector_helper_add(connector, &connector_helper_funcs);
+	ret = drm_sysfs_connector_add(connector);
+	if (ret < 0)
+		return ERR_PTR(ret);
+
+	drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
+	drm_object_property_set_value(&connector->base,
+		rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF);
+
+	ret = drm_mode_connector_attach_encoder(connector, &renc->encoder);
+	if (ret < 0)
+		return ERR_PTR(ret);
+
+	connector->encoder = &renc->encoder;
+
+	return rcon;
+}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_connector.h b/drivers/gpu/drm/rcar-du/rcar_du_connector.h
new file mode 100644
index 0000000..b9a0833
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rcar_du_connector.h
@@ -0,0 +1,36 @@
+/*
+ * rcar_du_connector.h  --  R-Car Display Unit Connector
+ *
+ * Copyright (C) 2013 Renesas Corporation
+ *
+ * Contact: Laurent Pinchart (laurent.pinchart@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.
+ */
+
+#ifndef __RCAR_DU_CONNECTOR_H__
+#define __RCAR_DU_CONNECTOR_H__
+
+#include <drm/drm_crtc.h>
+
+struct media_pad;
+struct rcar_du_device;
+struct rcar_du_encoder;
+
+struct rcar_du_connector {
+	struct drm_connector connector;
+	struct rcar_du_encoder *encoder;
+	struct media_pad *pad;
+};
+
+#define to_rcar_connector(c) \
+	container_of(c, struct rcar_du_connector, connector)
+
+struct rcar_du_connector *
+rcar_du_connector_create(struct rcar_du_device *rcdu,
+			 struct rcar_du_encoder *renc, struct media_pad *pad);
+
+#endif /* __RCAR_DU_CONNECTOR_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
index 43e7575..4e8bfff 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
@@ -15,11 +15,11 @@
 #define __RCAR_DU_CRTC_H__
 
 #include <linux/mutex.h>
-#include <linux/platform_data/rcar-du.h>
 
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 
+enum rcar_du_output;
 struct rcar_du_group;
 struct rcar_du_plane;
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 0a9f1bb..eda9ca9 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -15,6 +15,8 @@
 #include <linux/io.h>
 #include <linux/mm.h>
 #include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_data/rcar-du.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
 #include <linux/slab.h>
@@ -30,6 +32,153 @@
 #include "rcar_du_regs.h"
 
 /* -----------------------------------------------------------------------------
+ * Display Entities
+ */
+
+static int rcdu_entity_set_stream(struct display_entity *ent, unsigned int port,
+				  enum display_entity_stream_state state)
+{
+	return 0;
+}
+
+static const struct display_entity_video_ops rcdu_entity_video_ops = {
+	.set_stream = rcdu_entity_set_stream,
+};
+
+static const struct display_entity_ops rcdu_entity_ops = {
+	.video = &rcdu_entity_video_ops,
+};
+
+static struct media_pad *rcar_du_find_remote_pad(struct rcar_du_device *rcdu,
+						 unsigned int local_pad)
+{
+	struct display_entity *entity;
+	unsigned int i;
+
+	list_for_each_entry(entity, &rcdu->notifier.done, list) {
+		const struct display_entity_graph_data *graph =
+			entity->match->data;
+		const struct display_entity_source_data *source =
+			graph->sources;
+
+		for (i = 0; i < entity->entity.num_pads; ++i) {
+			struct media_pad *pad = &entity->entity.pads[i];
+
+			if (pad->flags & MEDIA_PAD_FL_SOURCE)
+				continue;
+
+			if (!strcmp(source->name, "rcar-du") &&
+			   source->port == local_pad)
+				return pad;
+		}
+	}
+
+	return NULL;
+}
+
+static int rcar_du_create_local_links(struct rcar_du_device *rcdu)
+{
+	u32 link_flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED;
+	unsigned int i;
+
+	for (i = 0; i < rcdu->entity.entity.num_pads; ++i) {
+		struct media_pad *pad;
+		int ret;
+
+		pad = rcar_du_find_remote_pad(rcdu, i);
+		if (pad == NULL)
+			continue;
+
+		ret = media_entity_create_link(&rcdu->entity.entity, i,
+					       pad->entity, pad->index,
+					       link_flags);
+		if (ret < 0) {
+			dev_err(rcdu->dev,
+				"failed to create %s:%u -> %s:%u link\n",
+				rcdu->entity.entity.name, i,
+				pad->entity->name, pad->index);
+			return ret;
+		}
+	}
+
+	return 0;
+};
+
+static int rcar_du_graph_init(struct rcar_du_device *rcdu)
+{
+	struct display_entity *entity;
+	unsigned int num_pads;
+	unsigned int i;
+	int ret;
+
+	/* Count the number of output pads and initialize the DU entity. */
+	for (i = 0, num_pads = 0; rcdu->info->routes[i].output; ++i)
+		num_pads++;
+
+	rcdu->entity.dev = rcdu->dev;
+	rcdu->entity.ops = &rcdu_entity_ops;
+	strcpy(rcdu->entity.name, "R-Car DU");
+
+	ret = display_entity_init(&rcdu->entity, 0, num_pads);
+	if (ret < 0)
+		return ret;
+
+	/* Create links between all entities. In the non-DT case, this is a two
+	 * steps process, we first create links between all external entities,
+	 * and then between the DU entity and the external entities.
+	 */
+	if (rcdu->dev->of_node) {
+		ret = display_of_entity_link_graph(rcdu->dev,
+						   &rcdu->notifier.done,
+						   &rcdu->entity);
+	} else {
+		ret = display_entity_link_graph(rcdu->dev,
+						&rcdu->notifier.done);
+		if (!ret)
+			ret = rcar_du_create_local_links(rcdu);
+	}
+
+	if (ret < 0) {
+		dev_err(rcdu->dev, "unable to link graph\n");
+		return ret;
+	}
+
+	/* Register the media device and all entities. */
+	rcdu->mdev.dev = rcdu->dev;
+	strlcpy(rcdu->mdev.model, dev_name(rcdu->dev),
+		sizeof(rcdu->mdev.model));
+
+	ret = media_device_register(&rcdu->mdev);
+	if (ret < 0)
+		return ret;
+
+	list_for_each_entry(entity, &rcdu->notifier.done, list) {
+		ret = display_entity_register(&rcdu->mdev, entity);
+		if (ret < 0)
+			return ret;
+	}
+
+	ret = display_entity_register(&rcdu->mdev, &rcdu->entity);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static void rcar_du_graph_cleanup(struct rcar_du_device *rcdu)
+{
+	struct display_entity *entity;
+
+	list_for_each_entry(entity, &rcdu->notifier.done, list)
+		display_entity_unregister(entity);
+
+	display_entity_unregister(&rcdu->entity);
+	display_entity_cleanup(&rcdu->entity);
+
+	media_device_unregister(&rcdu->mdev);
+}
+
+/* -----------------------------------------------------------------------------
  * DRM operations
  */
 
@@ -44,6 +193,8 @@ static int rcar_du_unload(struct drm_device *dev)
 	drm_mode_config_cleanup(dev);
 	drm_vblank_cleanup(dev);
 
+	rcar_du_graph_cleanup(rcdu);
+
 	dev->irq_enabled = 0;
 	dev->dev_private = NULL;
 
@@ -53,25 +204,10 @@ static int rcar_du_unload(struct drm_device *dev)
 static int rcar_du_load(struct drm_device *dev, unsigned long flags)
 {
 	struct platform_device *pdev = dev->platformdev;
-	struct rcar_du_platform_data *pdata = pdev->dev.platform_data;
-	struct rcar_du_device *rcdu;
+	struct rcar_du_device *rcdu = platform_get_drvdata(pdev);
 	struct resource *mem;
 	int ret;
 
-	if (pdata == NULL) {
-		dev_err(dev->dev, "no platform data\n");
-		return -ENODEV;
-	}
-
-	rcdu = devm_kzalloc(&pdev->dev, sizeof(*rcdu), GFP_KERNEL);
-	if (rcdu == NULL) {
-		dev_err(dev->dev, "failed to allocate private data\n");
-		return -ENOMEM;
-	}
-
-	rcdu->dev = &pdev->dev;
-	rcdu->pdata = pdata;
-	rcdu->info = (struct rcar_du_device_info *)pdev->id_entry->driver_data;
 	rcdu->ddev = dev;
 	dev->dev_private = rcdu;
 
@@ -81,6 +217,13 @@ static int rcar_du_load(struct drm_device *dev, unsigned long flags)
 	if (IS_ERR(rcdu->mmio))
 		return PTR_ERR(rcdu->mmio);
 
+	/* Display Entities */
+	ret = rcar_du_graph_init(rcdu);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to initialize display entities\n");
+		goto done;
+	}
+
 	/* DRM/KMS objects */
 	ret = rcar_du_modeset_init(rcdu);
 	if (ret < 0) {
@@ -97,8 +240,6 @@ static int rcar_du_load(struct drm_device *dev, unsigned long flags)
 
 	dev->irq_enabled = 1;
 
-	platform_set_drvdata(pdev, rcdu);
-
 done:
 	if (ret)
 		rcar_du_unload(dev);
@@ -218,33 +359,23 @@ static const struct dev_pm_ops rcar_du_pm_ops = {
  * Platform driver
  */
 
-static int rcar_du_probe(struct platform_device *pdev)
-{
-	return drm_platform_init(&rcar_du_driver, pdev);
-}
-
-static int rcar_du_remove(struct platform_device *pdev)
-{
-	drm_platform_exit(&rcar_du_driver, pdev);
-
-	return 0;
-}
-
 static const struct rcar_du_device_info rcar_du_r8a7779_info = {
 	.features = 0,
 	.num_crtcs = 2,
-	.routes = {
+	.routes = (const struct rcar_du_output_routing[]) {
 		/* R8A7779 has two RGB outputs and one (currently unsupported)
 		 * TCON output.
 		 */
-		[RCAR_DU_OUTPUT_DPAD0] = {
+		{
+			.output = RCAR_DU_OUTPUT_DPAD0,
 			.possible_crtcs = BIT(0),
 			.encoder_type = DRM_MODE_ENCODER_NONE,
-		},
-		[RCAR_DU_OUTPUT_DPAD1] = {
+		}, {
+			.output = RCAR_DU_OUTPUT_DPAD1,
 			.possible_crtcs = BIT(1) | BIT(0),
 			.encoder_type = DRM_MODE_ENCODER_NONE,
 		},
+		{ },
 	},
 	.num_lvds = 0,
 };
@@ -253,22 +384,24 @@ static const struct rcar_du_device_info rcar_du_r8a7790_info = {
 	.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_ALIGN_128B
 		  | RCAR_DU_FEATURE_DEFR8,
 	.num_crtcs = 3,
-	.routes = {
+	.routes = (const struct rcar_du_output_routing[]) {
 		/* R8A7790 has one RGB output, two LVDS outputs and one
 		 * (currently unsupported) TCON output.
 		 */
-		[RCAR_DU_OUTPUT_DPAD0] = {
+		{
+			.output = RCAR_DU_OUTPUT_DPAD0,
 			.possible_crtcs = BIT(2) | BIT(1) | BIT(0),
 			.encoder_type = DRM_MODE_ENCODER_NONE,
-		},
-		[RCAR_DU_OUTPUT_LVDS0] = {
+		}, {
+			.output = RCAR_DU_OUTPUT_LVDS0,
 			.possible_crtcs = BIT(0),
 			.encoder_type = DRM_MODE_ENCODER_LVDS,
-		},
-		[RCAR_DU_OUTPUT_LVDS1] = {
+		}, {
+			.output = RCAR_DU_OUTPUT_LVDS1,
 			.possible_crtcs = BIT(2) | BIT(1),
 			.encoder_type = DRM_MODE_ENCODER_LVDS,
 		},
+		{ },
 	},
 	.num_lvds = 2,
 };
@@ -278,9 +411,72 @@ static const struct platform_device_id rcar_du_id_table[] = {
 	{ "rcar-du-r8a7790", (kernel_ulong_t)&rcar_du_r8a7790_info },
 	{ }
 };
-
 MODULE_DEVICE_TABLE(platform, rcar_du_id_table);
 
+static const struct of_device_id rcar_du_of_table[] = {
+	{ .compatible = "renesas,du-r8a7779", .data = &rcar_du_r8a7779_info },
+	{ .compatible = "renesas,du-r8a7790", .data = &rcar_du_r8a7790_info },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, rcar_du_of_table);
+
+static int rcar_du_notifier_complete(struct display_entity_notifier *notifier)
+{
+	struct platform_device *pdev = to_platform_device(notifier->dev);
+
+	return drm_platform_init(&rcar_du_driver, pdev);
+}
+
+static int rcar_du_probe(struct platform_device *pdev)
+{
+	struct rcar_du_platform_data *pdata = pdev->dev.platform_data;
+	struct device_node *np = pdev->dev.of_node;
+	struct rcar_du_device *rcdu;
+	int ret;
+
+	rcdu = devm_kzalloc(&pdev->dev, sizeof(*rcdu), GFP_KERNEL);
+	if (rcdu == NULL)
+		return -ENOMEM;
+
+	rcdu->dev = &pdev->dev;
+
+	if (np)
+		rcdu->info = of_match_device(rcar_du_of_table, rcdu->dev)->data;
+	else
+		rcdu->info = (void *)platform_get_device_id(pdev)->driver_data;
+
+	platform_set_drvdata(pdev, rcdu);
+
+	rcdu->notifier.dev = rcdu->dev;
+	rcdu->notifier.complete = rcar_du_notifier_complete;
+
+	if (np) {
+		ret = display_of_entity_build_notifier(&rcdu->notifier, np);
+	} else if (pdata) {
+		ret = display_entity_build_notifier(&rcdu->notifier,
+						    pdata->graph);
+	} else {
+		dev_err(&pdev->dev, "no platform data");
+		ret = -ENXIO;
+	}
+
+	if (ret < 0)
+		return ret;
+
+	return display_entity_register_notifier(&rcdu->notifier);
+}
+
+static int rcar_du_remove(struct platform_device *pdev)
+{
+	struct rcar_du_device *rcdu = platform_get_drvdata(pdev);
+
+	display_entity_unregister_notifier(&rcdu->notifier);
+
+	drm_platform_exit(&rcar_du_driver, pdev);
+
+	return 0;
+}
+
 static struct platform_driver rcar_du_platform_driver = {
 	.probe		= rcar_du_probe,
 	.remove		= rcar_du_remove,
@@ -288,6 +484,7 @@ static struct platform_driver rcar_du_platform_driver = {
 		.owner	= THIS_MODULE,
 		.name	= "rcar-du",
 		.pm	= &rcar_du_pm_ops,
+		.of_match_table = of_match_ptr(rcar_du_of_table),
 	},
 	.id_table	= rcar_du_id_table,
 };
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index 65d2d63..49338e1 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -15,7 +15,8 @@
 #define __RCAR_DU_DRV_H__
 
 #include <linux/kernel.h>
-#include <linux/platform_data/rcar-du.h>
+#include <media/media-device.h>
+#include <video/display.h>
 
 #include "rcar_du_crtc.h"
 #include "rcar_du_group.h"
@@ -31,16 +32,28 @@ struct rcar_du_lvdsenc;
 #define RCAR_DU_FEATURE_ALIGN_128B	(1 << 1)	/* Align pitches to 128 bytes */
 #define RCAR_DU_FEATURE_DEFR8		(1 << 2)	/* Has DEFR8 register */
 
+enum rcar_du_output {
+	RCAR_DU_OUTPUT_NONE,
+	RCAR_DU_OUTPUT_DPAD0,
+	RCAR_DU_OUTPUT_DPAD1,
+	RCAR_DU_OUTPUT_LVDS0,
+	RCAR_DU_OUTPUT_LVDS1,
+	RCAR_DU_OUTPUT_TCON,
+	RCAR_DU_OUTPUT_MAX,
+};
+
 /*
  * struct rcar_du_output_routing - Output routing specification
+ * @output: DU output
  * @possible_crtcs: bitmask of possible CRTCs for the output
  * @encoder_type: DRM type of the internal encoder associated with the output
  *
  * The DU has 5 possible outputs (DPAD0/1, LVDS0/1, TCON). Output routing data
- * specify the valid SoC outputs, which CRTCs can drive the output, and the type
- * of in-SoC encoder for the output.
+ * specify an SoC output, which CRTCs can drive it, and the type of in-SoC
+ * encoder for the output.
  */
 struct rcar_du_output_routing {
+	enum rcar_du_output output;
 	unsigned int possible_crtcs;
 	unsigned int encoder_type;
 };
@@ -49,23 +62,26 @@ struct rcar_du_output_routing {
  * struct rcar_du_device_info - DU model-specific information
  * @features: device features (RCAR_DU_FEATURE_*)
  * @num_crtcs: total number of CRTCs
- * @routes: array of CRTC to output routes, indexed by output (RCAR_DU_OUTPUT_*)
+ * @routes: array of CRTC to output routes, indexed by port number
  * @num_lvds: number of internal LVDS encoders
  */
 struct rcar_du_device_info {
 	unsigned int features;
 	unsigned int num_crtcs;
-	struct rcar_du_output_routing routes[RCAR_DU_OUTPUT_MAX];
+	const struct rcar_du_output_routing *routes;
 	unsigned int num_lvds;
 };
 
 struct rcar_du_device {
 	struct device *dev;
-	const struct rcar_du_platform_data *pdata;
 	const struct rcar_du_device_info *info;
 
 	void __iomem *mmio;
 
+	struct media_device mdev;
+	struct display_entity entity;
+	struct display_entity_notifier notifier;
+
 	struct drm_device *ddev;
 	struct drm_fbdev_cma *fbdev;
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
index 3daa7a1..9991fb0 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c
@@ -20,25 +20,7 @@
 #include "rcar_du_drv.h"
 #include "rcar_du_encoder.h"
 #include "rcar_du_kms.h"
-#include "rcar_du_lvdscon.h"
 #include "rcar_du_lvdsenc.h"
-#include "rcar_du_vgacon.h"
-
-/* -----------------------------------------------------------------------------
- * Common connector functions
- */
-
-struct drm_encoder *
-rcar_du_connector_best_encoder(struct drm_connector *connector)
-{
-	struct rcar_du_connector *rcon = to_rcar_connector(connector);
-
-	return &rcon->encoder->encoder;
-}
-
-/* -----------------------------------------------------------------------------
- * Encoder
- */
 
 static void rcar_du_encoder_dpms(struct drm_encoder *encoder, int mode)
 {
@@ -139,10 +121,9 @@ static const struct drm_encoder_funcs encoder_funcs = {
 	.destroy = drm_encoder_cleanup,
 };
 
-int rcar_du_encoder_init(struct rcar_du_device *rcdu,
-			 enum rcar_du_encoder_type type,
-			 enum rcar_du_output output,
-			 const struct rcar_du_encoder_data *data)
+struct rcar_du_encoder *
+rcar_du_encoder_create(struct rcar_du_device *rcdu, unsigned int port,
+		       struct media_pad *pad)
 {
 	struct rcar_du_encoder *renc;
 	unsigned int encoder_type;
@@ -150,11 +131,13 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
 
 	renc = devm_kzalloc(rcdu->dev, sizeof(*renc), GFP_KERNEL);
 	if (renc == NULL)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
-	renc->output = output;
+	renc->port = port;
+	renc->output = rcdu->info->routes[port].output;
 
-	switch (output) {
+	/* Do we have an internal LVDS encoder? */
+	switch (renc->output) {
 	case RCAR_DU_OUTPUT_LVDS0:
 		renc->lvds = rcdu->lvds[0];
 		break;
@@ -167,36 +150,44 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
 		break;
 	}
 
-	switch (type) {
-	case RCAR_DU_ENCODER_VGA:
-		encoder_type = DRM_MODE_ENCODER_DAC;
-		break;
-	case RCAR_DU_ENCODER_LVDS:
-		encoder_type = DRM_MODE_ENCODER_LVDS;
-		break;
-	case RCAR_DU_ENCODER_NONE:
-	default:
+	/* Find the encoder type. */
+	if (pad) {
+		struct display_entity *entity = to_display_entity(pad->entity);
+		struct display_entity_interface_params params;
+
+		ret = display_entity_get_params(entity, pad->index, &params);
+		if (ret < 0) {
+			dev_dbg(rcdu->dev,
+				"failed to retrieve encoder %s parameters\n",
+				entity->name);
+			return ERR_PTR(ret);
+		}
+
+		switch (params.type) {
+		case DISPLAY_ENTITY_INTERFACE_DPI:
+		case DISPLAY_ENTITY_INTERFACE_DBI:
+		default:
+			encoder_type = DRM_MODE_ENCODER_NONE;
+			break;
+		case DISPLAY_ENTITY_INTERFACE_LVDS:
+			encoder_type = DRM_MODE_ENCODER_DAC;
+			break;
+		case DISPLAY_ENTITY_INTERFACE_VGA:
+			encoder_type = DRM_MODE_ENCODER_DAC;
+			break;
+		}
+	} else {
 		/* No external encoder, use the internal encoder type. */
-		encoder_type = rcdu->info->routes[output].encoder_type;
-		break;
+		encoder_type = rcdu->info->routes[port].encoder_type;
 	}
 
+	/* Initialize the encoder. */
 	ret = drm_encoder_init(rcdu->ddev, &renc->encoder, &encoder_funcs,
 			       encoder_type);
 	if (ret < 0)
-		return ret;
+		return ERR_PTR(ret);
 
 	drm_encoder_helper_add(&renc->encoder, &encoder_helper_funcs);
 
-	switch (encoder_type) {
-	case DRM_MODE_ENCODER_LVDS:
-		return rcar_du_lvds_connector_init(rcdu, renc,
-						   &data->connector.lvds.panel);
-
-	case DRM_MODE_ENCODER_DAC:
-		return rcar_du_vga_connector_init(rcdu, renc);
-
-	default:
-		return -EINVAL;
-	}
+	return renc;
 }
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
index 0e5a65e..7a19d5b 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h
@@ -14,15 +14,15 @@
 #ifndef __RCAR_DU_ENCODER_H__
 #define __RCAR_DU_ENCODER_H__
 
-#include <linux/platform_data/rcar-du.h>
-
 #include <drm/drm_crtc.h>
 
+struct media_pad;
 struct rcar_du_device;
 struct rcar_du_lvdsenc;
 
 struct rcar_du_encoder {
 	struct drm_encoder encoder;
+	unsigned int port;
 	enum rcar_du_output output;
 	struct rcar_du_lvdsenc *lvds;
 };
@@ -30,20 +30,8 @@ struct rcar_du_encoder {
 #define to_rcar_encoder(e) \
 	container_of(e, struct rcar_du_encoder, encoder)
 
-struct rcar_du_connector {
-	struct drm_connector connector;
-	struct rcar_du_encoder *encoder;
-};
-
-#define to_rcar_connector(c) \
-	container_of(c, struct rcar_du_connector, connector)
-
-struct drm_encoder *
-rcar_du_connector_best_encoder(struct drm_connector *connector);
-
-int rcar_du_encoder_init(struct rcar_du_device *rcdu,
-			 enum rcar_du_encoder_type type,
-			 enum rcar_du_output output,
-			 const struct rcar_du_encoder_data *data);
+struct rcar_du_encoder *
+rcar_du_encoder_create(struct rcar_du_device *rcdu, unsigned int port,
+		       struct media_pad *pad);
 
 #endif /* __RCAR_DU_ENCODER_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index b31ac08..2dc9e80 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -17,6 +17,7 @@
 #include <drm/drm_fb_cma_helper.h>
 #include <drm/drm_gem_cma_helper.h>
 
+#include "rcar_du_connector.h"
 #include "rcar_du_crtc.h"
 #include "rcar_du_drv.h"
 #include "rcar_du_encoder.h"
@@ -179,6 +180,89 @@ static const struct drm_mode_config_funcs rcar_du_mode_config_funcs = {
 	.output_poll_changed = rcar_du_output_poll_changed,
 };
 
+/* -----------------------------------------------------------------------------
+ * Pipeline and Mode Setting Initialization
+ */
+
+static int rcar_du_pipe_init(struct rcar_du_device *rcdu, unsigned int port,
+			     struct media_pad *remote)
+{
+	struct media_pad *pad_encoder = NULL;
+	struct media_pad *pad_connector = remote;
+	struct rcar_du_encoder *renc;
+	struct rcar_du_connector *rcon;
+	struct media_entity *entity;
+
+	/* We need to expose one KMS encoder and one KMS connector for an
+	 * arbitrarily long chain of external entities. Walk the chain and map
+	 * the last entity to the connector, and the next-to-last entity to the
+	 * encoder.
+	 */
+
+	/* Start at the entity connected to the DU output. */
+	entity = remote->entity;
+
+	dev_dbg(rcdu->dev, "%s: starting at entity %s pad %u\n", __func__,
+		entity->name, remote->index);
+
+	while (1) {
+		struct media_link *next = NULL;
+		unsigned int i;
+
+		/* Search the entity for an output link. As we only support
+		 * linear pipelines, return an error if multiple output links
+		 * are found.
+		 */
+		dev_dbg(rcdu->dev,
+			"%s: searching for an output link on entity %s\n",
+			__func__, entity->name);
+
+		for (i = 0; i < entity->num_links; ++i) {
+			struct media_link *link = &entity->links[i];
+
+			if (link->source->entity != entity)
+				continue;
+
+			if (next)
+				return -EPIPE;
+
+			next = link;
+		}
+
+		if (next == NULL) {
+			dev_dbg(rcdu->dev, "%s: not output link found\n",
+				__func__);
+			break;
+		}
+
+		dev_dbg(rcdu->dev,
+			"%s: output link %s:%u -> %s:%u found\n", __func__,
+			next->source->entity->name, next->source->index,
+			next->sink->entity->name, next->sink->index);
+
+		pad_encoder = next->source;
+		pad_connector = next->sink;
+		entity = pad_connector->entity;
+	}
+
+	dev_dbg(rcdu->dev,
+		"%s: encoder pad %s/%u connector pad %s/%u\n", __func__,
+		pad_encoder ? pad_encoder->entity->name : NULL,
+		pad_encoder ? pad_encoder->index : 0,
+		pad_connector->entity->name, pad_connector->index);
+
+	/* Create the encoder and connector. */
+	renc = rcar_du_encoder_create(rcdu, port, pad_encoder);
+	if (IS_ERR(renc))
+		return PTR_ERR(renc);
+
+	rcon = rcar_du_connector_create(rcdu, renc, pad_connector);
+	if (IS_ERR(rcon))
+		return PTR_ERR(rcon);
+
+	return 0;
+}
+
 int rcar_du_modeset_init(struct rcar_du_device *rcdu)
 {
 	static const unsigned int mmio_offsets[] = {
@@ -188,6 +272,7 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
 	struct drm_device *dev = rcdu->ddev;
 	struct drm_encoder *encoder;
 	struct drm_fbdev_cma *fbdev;
+	unsigned int num_encoders = 0;
 	unsigned int num_groups;
 	unsigned int i;
 	int ret;
@@ -226,29 +311,26 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
 			return ret;
 	}
 
-	/* Initialize the encoders. */
+	/* Initialize the internal encoders. */
 	ret = rcar_du_lvdsenc_init(rcdu);
 	if (ret < 0)
 		return ret;
 
-	for (i = 0; i < rcdu->pdata->num_encoders; ++i) {
-		const struct rcar_du_encoder_data *pdata =
-			&rcdu->pdata->encoders[i];
-		const struct rcar_du_output_routing *route =
-			&rcdu->info->routes[pdata->output];
+	/* Create an encoder and a connector for each output connected to
+	 * external entities.
+	 */
+	for (i = 0; i < rcdu->entity.entity.num_pads; ++i) {
+		struct media_pad *pad;
 
-		if (pdata->type == RCAR_DU_ENCODER_UNUSED)
+		pad = media_entity_remote_pad(&rcdu->entity.entity.pads[i]);
+		if (pad == NULL)
 			continue;
 
-		if (pdata->output >= RCAR_DU_OUTPUT_MAX ||
-		    route->possible_crtcs == 0) {
-			dev_warn(rcdu->dev,
-				 "encoder %u references unexisting output %u, skipping\n",
-				 i, pdata->output);
-			continue;
-		}
+		ret = rcar_du_pipe_init(rcdu, i, pad);
+		if (ret < 0)
+			return ret;
 
-		rcar_du_encoder_init(rcdu, pdata->type, pdata->output, pdata);
+		num_encoders++;
 	}
 
 	/* Set the possible CRTCs and possible clones. There's always at least
@@ -258,10 +340,10 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 		struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
 		const struct rcar_du_output_routing *route =
-			&rcdu->info->routes[renc->output];
+			&rcdu->info->routes[renc->port];
 
 		encoder->possible_crtcs = route->possible_crtcs;
-		encoder->possible_clones = (1 << rcdu->pdata->num_encoders) - 1;
+		encoder->possible_clones = (1 << num_encoders) - 1;
 	}
 
 	/* Now that the CRTCs have been initialized register the planes. */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
deleted file mode 100644
index 4f3ba93..0000000
--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * rcar_du_lvdscon.c  --  R-Car Display Unit LVDS Connector
- *
- * Copyright (C) 2013 Renesas Corporation
- *
- * Contact: Laurent Pinchart (laurent.pinchart@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 <drm/drmP.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-
-#include "rcar_du_drv.h"
-#include "rcar_du_encoder.h"
-#include "rcar_du_kms.h"
-#include "rcar_du_lvdscon.h"
-
-struct rcar_du_lvds_connector {
-	struct rcar_du_connector connector;
-
-	const struct rcar_du_panel_data *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;
-
-	mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
-	mode->clock = lvdscon->panel->mode.clock;
-	mode->hdisplay = lvdscon->panel->mode.hdisplay;
-	mode->hsync_start = lvdscon->panel->mode.hsync_start;
-	mode->hsync_end = lvdscon->panel->mode.hsync_end;
-	mode->htotal = lvdscon->panel->mode.htotal;
-	mode->vdisplay = lvdscon->panel->mode.vdisplay;
-	mode->vsync_start = lvdscon->panel->mode.vsync_start;
-	mode->vsync_end = lvdscon->panel->mode.vsync_end;
-	mode->vtotal = lvdscon->panel->mode.vtotal;
-	mode->flags = lvdscon->panel->mode.flags;
-
-	drm_mode_set_name(mode);
-	drm_mode_probed_add(connector, mode);
-
-	return 1;
-}
-
-static int rcar_du_lvds_connector_mode_valid(struct drm_connector *connector,
-					    struct drm_display_mode *mode)
-{
-	return MODE_OK;
-}
-
-static const struct drm_connector_helper_funcs connector_helper_funcs = {
-	.get_modes = rcar_du_lvds_connector_get_modes,
-	.mode_valid = rcar_du_lvds_connector_mode_valid,
-	.best_encoder = rcar_du_connector_best_encoder,
-};
-
-static void rcar_du_lvds_connector_destroy(struct drm_connector *connector)
-{
-	drm_sysfs_connector_remove(connector);
-	drm_connector_cleanup(connector);
-}
-
-static enum drm_connector_status
-rcar_du_lvds_connector_detect(struct drm_connector *connector, bool force)
-{
-	return connector_status_connected;
-}
-
-static const struct drm_connector_funcs connector_funcs = {
-	.dpms = drm_helper_connector_dpms,
-	.detect = rcar_du_lvds_connector_detect,
-	.fill_modes = drm_helper_probe_single_connector_modes,
-	.destroy = rcar_du_lvds_connector_destroy,
-};
-
-int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
-				struct rcar_du_encoder *renc,
-				const struct rcar_du_panel_data *panel)
-{
-	struct rcar_du_lvds_connector *lvdscon;
-	struct drm_connector *connector;
-	int ret;
-
-	lvdscon = devm_kzalloc(rcdu->dev, sizeof(*lvdscon), GFP_KERNEL);
-	if (lvdscon == NULL)
-		return -ENOMEM;
-
-	lvdscon->panel = panel;
-
-	connector = &lvdscon->connector.connector;
-	connector->display_info.width_mm = panel->width_mm;
-	connector->display_info.height_mm = panel->height_mm;
-
-	ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs,
-				 DRM_MODE_CONNECTOR_LVDS);
-	if (ret < 0)
-		return ret;
-
-	drm_connector_helper_add(connector, &connector_helper_funcs);
-	ret = drm_sysfs_connector_add(connector);
-	if (ret < 0)
-		return ret;
-
-	drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
-	drm_object_property_set_value(&connector->base,
-		rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF);
-
-	ret = drm_mode_connector_attach_encoder(connector, &renc->encoder);
-	if (ret < 0)
-		return ret;
-
-	connector->encoder = &renc->encoder;
-	lvdscon->connector.encoder = renc;
-
-	return 0;
-}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h
deleted file mode 100644
index bff8683..0000000
--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * rcar_du_lvdscon.h  --  R-Car Display Unit LVDS Connector
- *
- * Copyright (C) 2013 Renesas Corporation
- *
- * Contact: Laurent Pinchart (laurent.pinchart@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.
- */
-
-#ifndef __RCAR_DU_LVDSCON_H__
-#define __RCAR_DU_LVDSCON_H__
-
-struct rcar_du_device;
-struct rcar_du_encoder;
-struct rcar_du_panel_data;
-
-int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
-				struct rcar_du_encoder *renc,
-				const struct rcar_du_panel_data *panel);
-
-#endif /* __RCAR_DU_LVDSCON_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
deleted file mode 100644
index 72312f7..0000000
--- a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * rcar_du_vgacon.c  --  R-Car Display Unit VGA Connector
- *
- * Copyright (C) 2013 Renesas Corporation
- *
- * Contact: Laurent Pinchart (laurent.pinchart@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 <drm/drmP.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
-
-#include "rcar_du_drv.h"
-#include "rcar_du_encoder.h"
-#include "rcar_du_kms.h"
-#include "rcar_du_vgacon.h"
-
-static int rcar_du_vga_connector_get_modes(struct drm_connector *connector)
-{
-	return drm_add_modes_noedid(connector, 1280, 768);
-}
-
-static int rcar_du_vga_connector_mode_valid(struct drm_connector *connector,
-					    struct drm_display_mode *mode)
-{
-	return MODE_OK;
-}
-
-static const struct drm_connector_helper_funcs connector_helper_funcs = {
-	.get_modes = rcar_du_vga_connector_get_modes,
-	.mode_valid = rcar_du_vga_connector_mode_valid,
-	.best_encoder = rcar_du_connector_best_encoder,
-};
-
-static void rcar_du_vga_connector_destroy(struct drm_connector *connector)
-{
-	drm_sysfs_connector_remove(connector);
-	drm_connector_cleanup(connector);
-}
-
-static enum drm_connector_status
-rcar_du_vga_connector_detect(struct drm_connector *connector, bool force)
-{
-	return connector_status_connected;
-}
-
-static const struct drm_connector_funcs connector_funcs = {
-	.dpms = drm_helper_connector_dpms,
-	.detect = rcar_du_vga_connector_detect,
-	.fill_modes = drm_helper_probe_single_connector_modes,
-	.destroy = rcar_du_vga_connector_destroy,
-};
-
-int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,
-			       struct rcar_du_encoder *renc)
-{
-	struct rcar_du_connector *rcon;
-	struct drm_connector *connector;
-	int ret;
-
-	rcon = devm_kzalloc(rcdu->dev, sizeof(*rcon), GFP_KERNEL);
-	if (rcon == NULL)
-		return -ENOMEM;
-
-	connector = &rcon->connector;
-	connector->display_info.width_mm = 0;
-	connector->display_info.height_mm = 0;
-
-	ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs,
-				 DRM_MODE_CONNECTOR_VGA);
-	if (ret < 0)
-		return ret;
-
-	drm_connector_helper_add(connector, &connector_helper_funcs);
-	ret = drm_sysfs_connector_add(connector);
-	if (ret < 0)
-		return ret;
-
-	drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
-	drm_object_property_set_value(&connector->base,
-		rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF);
-
-	ret = drm_mode_connector_attach_encoder(connector, &renc->encoder);
-	if (ret < 0)
-		return ret;
-
-	connector->encoder = &renc->encoder;
-	rcon->encoder = renc;
-
-	return 0;
-}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.h b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.h
deleted file mode 100644
index b12b0cf..0000000
--- a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * rcar_du_vgacon.h  --  R-Car Display Unit VGA Connector
- *
- * Copyright (C) 2013 Renesas Corporation
- *
- * Contact: Laurent Pinchart (laurent.pinchart@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.
- */
-
-#ifndef __RCAR_DU_VGACON_H__
-#define __RCAR_DU_VGACON_H__
-
-struct rcar_du_device;
-struct rcar_du_encoder;
-
-int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,
-			       struct rcar_du_encoder *renc);
-
-#endif /* __RCAR_DU_VGACON_H__ */
diff --git a/include/linux/platform_data/rcar-du.h b/include/linux/platform_data/rcar-du.h
index 1a2e990..b424b75 100644
--- a/include/linux/platform_data/rcar-du.h
+++ b/include/linux/platform_data/rcar-du.h
@@ -14,61 +14,10 @@
 #ifndef __RCAR_DU_H__
 #define __RCAR_DU_H__
 
-#include <drm/drm_mode.h>
-
-enum rcar_du_output {
-	RCAR_DU_OUTPUT_DPAD0,
-	RCAR_DU_OUTPUT_DPAD1,
-	RCAR_DU_OUTPUT_LVDS0,
-	RCAR_DU_OUTPUT_LVDS1,
-	RCAR_DU_OUTPUT_TCON,
-	RCAR_DU_OUTPUT_MAX,
-};
-
-enum rcar_du_encoder_type {
-	RCAR_DU_ENCODER_UNUSED = 0,
-	RCAR_DU_ENCODER_NONE,
-	RCAR_DU_ENCODER_VGA,
-	RCAR_DU_ENCODER_LVDS,
-};
-
-struct rcar_du_panel_data {
-	unsigned int width_mm;		/* Panel width in mm */
-	unsigned int height_mm;		/* Panel height in mm */
-	struct drm_mode_modeinfo mode;
-};
-
-struct rcar_du_connector_lvds_data {
-	struct rcar_du_panel_data panel;
-};
-
-struct rcar_du_connector_vga_data {
-	/* TODO: Add DDC information for EDID retrieval */
-};
-
-/*
- * struct rcar_du_encoder_data - Encoder platform data
- * @type: the encoder type (RCAR_DU_ENCODER_*)
- * @output: the DU output the connector is connected to (RCAR_DU_OUTPUT_*)
- * @connector.lvds: platform data for LVDS connectors
- * @connector.vga: platform data for VGA connectors
- *
- * Encoder platform data describes an on-board encoder, its associated DU SoC
- * output, and the connector.
- */
-struct rcar_du_encoder_data {
-	enum rcar_du_encoder_type type;
-	enum rcar_du_output output;
-
-	union {
-		struct rcar_du_connector_lvds_data lvds;
-		struct rcar_du_connector_vga_data vga;
-	} connector;
-};
+#include <video/display.h>
 
 struct rcar_du_platform_data {
-	struct rcar_du_encoder_data *encoders;
-	unsigned int num_encoders;
+	const struct display_entity_graph_data *graph;
 };
 
 #endif /* __RCAR_DU_H__ */
-- 
1.8.1.5

^ permalink raw reply related	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 06/19] video: display: OF support
  2013-08-09 17:14 ` [PATCH/RFC v3 06/19] video: display: OF support Laurent Pinchart
@ 2013-08-13 14:37   ` Philipp Zabel
  2013-08-21  1:02     ` Laurent Pinchart
  0 siblings, 1 reply; 83+ messages in thread
From: Philipp Zabel @ 2013-08-13 14:37 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-fbdev, Sebastien Guiriec, dri-devel, Jesse Barnes,
	Benjamin Gaignard, Tom Gall, Kyungmin Park, Tomi Valkeinen,
	linux-media, Stephen Warren, Mark Zhang, Stéphane Marchesin,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

Hi Laurent,

thanks for this update. I'm very happy about the move to the display
entity model, given that the i.MX6 IPU has both drm/display and
v4l2/capture ports in a single device - this will allow to use a unified
device tree binding scheme. I'm still trying to see how this all fits
together, so far I have only one comment, below.

Am Freitag, den 09.08.2013, 19:14 +0200 schrieb Laurent Pinchart:
[...]
> +static int display_of_parse_dt(struct display_entity_notifier *notifier,
> +			       struct list_head *entities,
> +			       struct device_node *node)
> +{
> +	struct display_entity_of *entity;
> +	struct device_node *remote;
> +	struct device_node *ep = NULL;
> +	struct device_node *next;
> +	unsigned int num_entities = 0;
> +	int ret = 0;
> +
> +	/* Walk the device tree and build a list of nodes. */
> +	dev_dbg(notifier->dev, "parsing node %s\n", node->full_name);
> +
> +	while (1) {
> +		next = display_of_get_next_endpoint(node, ep);
> +		if (next == NULL)
> +			break;
> +
> +		of_node_put(ep);
> +		ep = next;
> +
> +		dev_dbg(notifier->dev, "handling endpoint %s\n", ep->full_name);
> +
> +		remote = display_of_get_remote_port_parent(ep);
> +		if (remote == NULL)
> +			continue;
> +
> +		/* Skip entities that we have already processed. */
> +		if (display_of_find_entity(entities, remote) || remote == node) {
> +			dev_dbg(notifier->dev,
> +				"entity %s already in list, skipping\n",
> +				remote->full_name);
> +			continue;
> +		}

device tree nodes with status = "disabled" should be skipped here:

                if (!of_device_is_available(remote)) {
                        dev_dbg(notifier->dev,
                                "entity %s is disabled, skipping\n",
                                remote->full_name);
                        continue;
                }

Otherwise the completion notification will never be delivered if there
are any disabled entities in the graph.

> +		entity = kzalloc(sizeof(*entity), GFP_KERNEL);
> +		if (entity == NULL) {
> +			of_node_put(remote);
> +			ret = -ENOMEM;
> +			break;
> +		}
> +
> +		dev_dbg(notifier->dev, "adding remote entity %s to list\n",
> +			remote->full_name);
> +
> +		entity->node = remote;
> +		list_add_tail(&entity->list, entities);
> +		num_entities++;
> +	}
> +
> +	of_node_put(ep);
> +
> +	if (ret < 0)
> +		return ret;
> +
> +	return num_entities;
> +}
[...]

regards
Philipp

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
  2013-08-09 17:14 [PATCH/RFC v3 00/19] Common Display Framework Laurent Pinchart
                   ` (18 preceding siblings ...)
  2013-08-09 17:15 ` [PATCH/RFC v3 19/19] drm/rcar-du: Port to the Common Display Framework Laurent Pinchart
@ 2013-08-14  0:43 ` Rob Clark
  2013-08-20 15:24   ` Laurent Pinchart
  2013-09-02 11:06 ` Tomi Valkeinen
  2013-09-30 13:48 ` Tomi Valkeinen
  21 siblings, 1 reply; 83+ messages in thread
From: Rob Clark @ 2013-08-14  0:43 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-fbdev, Sebastien Guiriec, dri-devel, Jesse Barnes,
	Benjamin Gaignard, Tom Gall, Ragesh Radhakrishnan,
	Tomi Valkeinen, linux-media, Stephen Warren, Mark Zhang,
	Stéphane Marchesin, Alexandre Courbot, Thomas Petazzoni,
	Sunil Joshi, Kyungmin Park, Maxime Ripard, Vikas Sajjan,
	Marcus Lorentzon

On Fri, Aug 9, 2013 at 1:14 PM, Laurent Pinchart
<laurent.pinchart+renesas@ideasonboard.com> wrote:
> Hi everybody,
>
> Here's the third RFC of the Common Display Framework.
>
> I won't repeat all the background information from the versions one and two
> here, you can read it at http://lwn.net/Articles/512363/ and
> http://lwn.net/Articles/526965/.
>
> This RFC isn't final. Given the high interest in CDF and the urgent tasks that
> kept delaying the next version of the patch set, I've decided to release v3
> before completing all parts of the implementation. Known missing items are
>
> - documentation: kerneldoc and this cover letter should provide basic
>   information, more extensive documentation will likely make it to v4.
>
> - pipeline configuration and control: generic code to configure and control
>   display pipelines (in a nutshell, translating high-level mode setting and
>   DPMS calls to low-level entity operations) is missing. Video and stream
>   control operations have been carried over from v2, but will need to be
>   revised for v4.
>
> - DSI support: I still have no DSI hardware I can easily test the code on.

tbh, I kinda think that DSI and bridge chips are the things we should
focus on first.. that seems what is most important for current and new
hardware.  Back-filling to handle older/simpler panels can be done
later.

>
> Special thanks go to
>
> - Renesas for inviting me to LinuxCon Japan 2013 where I had the opportunity
>   to validate the CDF v3 concepts with Alexandre Courbot (NVidia) and Tomasz
>   Figa (Samsung).
>
> - Tomi Valkeinen (TI) for taking the time to deeply brainstorm v3 with me.
>
> - Linaro for inviting me to Linaro Connect Europe 2013, the discussions we had
>   there greatly helped moving CDF forward.
>
> - And of course all the developers who showed interest in CDF and spent time
>   sharing ideas, reviewing patches and testing code.
>
> I have to confess I was a bit lost and discouraged after all the CDF-related
> meetings during which we have discussed how to move from v2 to v3. With every
> meeting I was hoping to run the implementation through use cases of various
> interesting parties and narrow down the scope of the huge fuzzy beast that CDF
> was. With every meeting the scope actually broadened, with no clear path at
> sight anywhere.
>
> Earlier this year I was about to drop one of the requirements on which I had
> based CDF v2: sharing drivers between DRM/KMS and V4L2. With only two HDMI
> transmitters as use cases for that feature (with only out-of-tree drivers so
> far), I just thought the involved completely wasn't worth it and that I should
> implement CDF v3 as a DRM/KMS-only helper framework. However, a seemingly
> unrelated discussion with Xilinx developers showed me that hybrid SoC-FPGA
> platforms such as the Xilinx Zynq 7000 have a larger library of IP cores that
> can be used in camera capture pipelines and in display pipelines. The two use
> cases suddenly became tens or even hundreds of use cases that I couldn't
> ignore anymore.

Hmm, I'm still not really convinced ;-)

Or maybe, put another way, I still think we should still optimize for
the common case.  I mean I'm sure you *can* design hw that has an
LVDS->DP bridge in the capture path, and if you had something like an
FPGA where that was cheap to do maybe you even would (for fun).  But
if in the real world, there are only one or two cases of actual hw
using the same bridge in a capture pipeline which is normally used in
display pipelines, then duplicating some small bit of code for that
abnormal case if it makes things easier for the common case, seems
like a reasonable trade-off to me.

I mean, take a DSI panel driver, for example.. anything but a trivial
panel driver, you are going to want to expose some custom properties
on the connector for controlling non-standard features.  So you end up
with both cdf_foo for the common part, and drm_foo for gluing in the
properties.  And now these two parts which otherwise would be one, end
up having to stay in sync merged through different trees, etc.  It
seems a lot like making my life more difficult for a fairly
hypothetical gain ;-)

Or, take an hdmi or DP bridge.  To use any of the common
infrastructure/helpers in drm, you end up implementing a generic
interface, where both the producer and consumer is inside drm.  Which
just seems a bit pointless and extra hoops to jump through.
Especially when we discover that we need to extend/enhance the common
interface outside of drm to make it work.  (I'm thinking of
display_entity_control_ops::get_modes() here, but I'm sure there are
more examples.)  And I think we'll run into similar issues with
display_entity_control_ops::set_state(), since the on<->off sequencing
can get hairy when the upstream/downstream entity is fed a clk by the
downstream/upstream entity.  And similarly, I think we'll go through a
few revisions of DSI panel/bus params before we have everything that
everyone needs.

(Don't get me wrong.. if we were starting from scratch, I'd tend to
think that stuff downstream of the crtc should share common framework
w/ v4l.. but we are pretty far from starting from scratch, and how to
get from where we are today to future is just as important as the end
result.)

BR,
-R

> CDF v3 is thus userspace API agnostic. It isn't tied to DRM/KMS or V4L2 and
> can be used by any kernel subsystem, potentially including FBDEV (although I
> won't personally wrote FBDEV support code, as I've already advocated for FBDEV
> to be deprecated).
>
> The code you are about to read is based on the concept of display entities
> introduced in v2. Diagrams related to the explanations below are available at
> http://ideasonboard.org/media/cdf/20130709-lce-cdf.pdf.
>
>
> Display Entities
> ----------------
>
> A display entity abstracts any hardware block that sources, processes or sinks
> display-related video streams. It offers an abstract API, implemented by display
> entity drivers, that is used by master drivers (such as the main display driver)
> to query, configure and control display pipelines.
>
> Display entities are connected to at least one video data bus, and optionally
> to a control bus. The video data busses carry display-related video data out
> of sources (such as a CRTC in a display controller) to sinks (such as a panel
> or a monitor), optionally going through transmitters, encoders, decoders,
> bridges or other similar devices. A CRTC or a panel will usually be connected
> to a single data bus, while an encoder or a transmitter will be connected to
> two data busses.
>
> The simple linear display pipelines we find in most embedded platforms at the
> moment are expected to grow more complex with time. CDF needs to accomodate
> those needs from the start to be, if not future-proof, at least present-proof
> at the time it will get merged in to mainline. For this reason display
> entities have data ports through which video streams flow in or out, with link
> objects representing the connections between those ports. A typical entity in
> a linear display pipeline will have one (for video source and video sink
> entities such as CRTCs or panels) or two ports (for video processing entities
> such as encoders), but more ports are allowed, and entities can be linked in
> complex non-linear pipelines.
>
> Readers might think that this model if extremely similar to the media
> controller graph model. They would be right, and given my background this is
> most probably not a coincidence. The CDF v3 implementation uses the in-kernel
> media controller framework to model the graph of display entities, with the
> display entity data structure inheriting from the media entity structure. The
> display pipeline graph topology will be automatically exposed to userspace
> through the media controller API as an added bonus. However, ussage of the
> media controller userspace API in applications is *not* mandatory, and the
> current CDF implementation doesn't use the media controller link setup
> userspace API to configure the display pipelines.
>
> While some display entities don't require any configuration (DPI panels are a
> good example), many of them are connected to a control bus accessible to the
> CPU. Control requests can be sent on a dedicated control bus (such as I2C or
> SPI) or multiplexed on a mixed control and data bus (such as DBI or DSI). To
> support both options the CDF display entity model separates the control and
> data busses in different APIs.
>
> Display entities are abstract object that must be implemented by a real
> device. The device sits on its control bus and is registered with the Linux
> device core and matched with his driver using the control bus specific API.
> The CDF doesn't create a display entity class or bus, display entity drivers
> thus standard Linux kernel drivers using existing busses. A DBI bus is added
> as part of this patch set, but strictly speaking this isn't part of CDF.
>
> When a display entity driver probes a device it must create an instance of the
> display_entity structure, initialize it and add it to the CDF core entities
> pool. The display entity exposes abstract operations through function
> pointers, and the entity driver must implement those operations. Those
> operations can act on either the whole entity or on a given port, depending on
> the operation. They are divided in two groups, control operations and video
> operations.
>
>
> Control Operations
> ------------------
>
> Control operations are called by upper-level drivers, usually in response to a
> request originating from userspace. They query or control the display entity
> state and operation. Currently defined control operations are
>
> - get_size(), to retrieve the entity physical size (applicable to panels only)
> - get_modes(), to retrieve the video modes supported at an entity port
> - get_params(), to retrieve the data bus parameters at an entity port
>
> - set_state(), to control the state of the entity (off, standby or on)
> - update(), to trigger a display update (for entities that implement manual
>   update, such as manual-update panels that store frames in their internal
>   frame buffer)
>
> The last two operations have been carried from v2 and will be reworked.
>
>
> Pipeline Control
> ----------------
>
> The figure on page 4 shows the control model for a linear pipeline. This
> differs significantly from CDF v2 where calls where forwarded from entity to
> entity using a Russian dolls model. v3 removes the need of neighbour awareness
> from entity drivers, simplifying the entity drivers. The complexity of pipeline
> configuration is moved to a central location called a pipeline controller
> instead of being spread out to all drivers.
>
> Pipeline controllers provide library functions that display drivers can use to
> control a pipeline. Several controllers can be implemented to accomodate the
> needs of various pipeline topologies and complexities, and display drivers can
> even implement their own pipeline control algorithm if needed. I'm working on a
> linear pipeline controller for the next version of the patch set.
>
> If pipeline controllers are responsible for propagating a pipeline configuration
> on all entity ports in the pipeline, entity drivers are responsible for
> propagating the configuration inside entities, from sink (input) to source
> (output) ports as illustrated on page 5. The rationale behind this is that
> knowledge of the entity internals is located in the entity driver, while
> knowledge of the pipeline belongs to the pipeline controller. The controller
> will thus configure the pipeline by performing the following steps:
>
> - applying a configuration on sink ports of an entity
> - read the configuration that has been propagated by the entity driver on its
>   source ports
> - optionally, modify the source port configuration (to configure custom timings,
>   scaling or other parameters, if supported by the entity)
> - propagate the source port configuration to the sink ports of the next entities
>   in the pipeline and start over
>
> Beside modifying the active configuration, the entities API will allow trying
> configurations without applying them to the hardware. As configuration of a port
> possibly depend on the configurations of the other ports, trying a configuration
> must be done at the entity level instead of the port level. The implementation
> will be based on the concept of configuration store objects that will store the
> configuration of all ports for a given entity. Each entity will have a single
> active configuration store, and test configuration stores will be created
> dynamically to try a configuration on an entity. The get and set operations
> implemented by the entity will receive a configuration store pointer, and active
> and test code paths in entity drivers will be identical, except for applying the
> configuration to the hardware for the active code path.
>
>
> Video Operations
> ----------------
>
> Video operations control the video stream state on entity ports. The only
> currently defined video operation is
>
> - set_stream(), to start (in continuous or single-shot mode) the video stream
>   on an entity port
>
> The call model for video operations differ from the control operations model
> described above. The set_stream() operation is called directly by downstream
> entities on upstream entities (from a video data bus point of view).
> Terminating entities in a pipeline (such as panels) will usually call the
> set_stream() operation in their set_state() handler, and intermediate entities
> will forward the set_stream() call upstream.
>
>
> Integration
> -----------
>
> The figure on page 8 describes how a panel driver, implemented using CDF as a
> display entity, interacts with the other components in the system. The use case
> is a simple pipeline made of a display controller and a panel.
>
> The display controller driver receives control request from userspace through
> DRM (or FBDEV) API calls. It processes the request and calls the panel driver
> through the CDF control operations API. The panel driver will then issue
> requests on its control bus (several possible control busses are shown on the
> figure, panel drivers typically use one of them only) and call video operations
> of the display controller on its left side to control the video stream.
>
>
> Registration and Notification
> -----------------------------
>
> Due to possibly complex dependencies between entities we can't guarantee that
> all entities part of the display pipeline will have been successfully probed
> when the master display controller driver is probed. For instance a panel can
> be a child of the DBI or DSI bus controlled by the display device, or use a
> clock provided by that device. We can't defer the display device probe until
> the panel is probed and also defer the panel device probe until the display
> device is probed. For this reason we need a notification system that allows
> entities to register themselves with the CDF core, and display controller
> drivers to get notified when entities they need are available.
>
> The notification system has been completely redesigned in v3. This version is
> based on the V4L2 asynchronous probing notification code, with large parts of
> the code shamelessly copied. This is an interim solution to let me play with
> the notification code as needed by CDF. I'm not a fan of code duplication, and
> will work on merging the CDF and V4L2 implementations in a later stage when
> CDF will reach a mature enough state.
>
> CDF manages a pool of entities and a list of notifiers. Notifiers are
> registered by master display drivers with an array of entities match
> descriptors. When an entity is added to the CDF entities pool, all notifiers
> are searched for a match. If a match is found, the corresponding notifier is
> called to notify the master display driver.
>
> The two currently supported match methods are platform match, which uses
> device names, and DT match, which uses DT node pointers. More match method
> might be added later if needed. Two helper functions exist to build a notifier
> from a list of platform device names (in the non-DT case) or a DT
> representation of the display pipeline topology.
>
> Once all required entities have been successfully found, the master display
> driver is responsible for creating media controller links between all entities
> in the pipeline. Two helper functions are also available to automate that
> process, one for the non-DT case and one for the DT case. Once again some
> DT-related code has been copied from the V4L2 DT code, I will work on merging
> both in a future version.
>
> Note that notification brings a different issue after registration, as display
> controller and display entity drivers would take a reference to each other.
> Those circular references would make driver unloading impossible. One possible
> solution to this problem would be to simulate an unplug event for the display
> entity, to force the display driver to release the dislay entities it uses. We
> would need a userspace API for that though. Better solutions would of course
> be welcome.
>
>
> Device Tree Bindings
> --------------------
>
> CDF entities device tree bindings are not documented yet. They describe both
> the graph topology and entity-specific information. The graph description uses
> the V4L2 DT bindings (which are actually not V4L2-specific) specified at
> Documentation/devicetree/bindings/media/video-interfaces.txt. Entity-specific
> information will be described in individual DT bindings documentation. The DPI
> panel driver uses the display timing bindings documented in
> Documentation/devicetree/bindings/video/display-timing.txt.
>
>
>
>
> Please note that most of the display entities on devices I own are just dumb
> panels with no control bus, and are thus not the best candidates to design a
> framework that needs to take complex panels' needs into account. This is why I
> hope to see you using the CDF with your display device and tell me what needs to
> be modified/improved/redesigned.
>
> This patch set is split as follows:
>
> - The first patch fixes a Kconfig namespace issue with the OMAP DSS panels. It
>   could be applied already independently of this series.
> - Patches 02/19 to 07/19 add the CDF core, including the notification system
>   and the graph and OF helpers.
> - Patch 08/19 adds a MIPI DBI bus. This isn't part of CDF strictly speaking,
>   but is needed for the DBI panel drivers.
> - Patches 09/19 to 13/19 add panel drivers, a VGA DAC driver and a VGA
>   connector driver.
> - Patches 14/19 to 18/19 add CDF-compliant reference board code and DT for the
>   Renesas Marzen and Lager boards.
> - Patch 19/19 port the Renesas R-Car Display Unit driver to CDF.
>
> The patches are available in my git tree at
>
>     git://linuxtv.org/pinchartl/fbdev.git cdf/v3
>     http://git.linuxtv.org/pinchartl/fbdev.git/shortlog/refs/heads/cdf/v3
>
> For convenience I've included modifications to the Renesas R-Car Display Unit
> driver to use the CDF. You can read the code to see how the driver uses CDF to
> interface panels. Please note that the rcar-du-drm implementation is still
> work in progress, its set_stream operation implementation doesn't enable and
> disable the video stream yet as it should.
>
> As already mentioned in v2, I will appreciate all reviews, comments,
> criticisms, ideas, remarks, ... If you can find a clever way to solve the
> cyclic references issue described above I'll buy you a beer at the next
> conference we will both attend. If you think the proposed solution is too
> complex, or too simple, I'm all ears, but I'll have more arguments this time
> than I had with v2 :-)
>
> Laurent Pinchart (19):
>   OMAPDSS: panels: Rename Kconfig options to OMAP2_DISPLAY_*
>   video: Add Common Display Framework core
>   video: display: Add video and stream control operations
>   video: display: Add display entity notifier
>   video: display: Graph helpers
>   video: display: OF support
>   video: display: Add pixel coding definitions
>   video: display: Add MIPI DBI bus support
>   video: panel: Add DPI panel support
>   video: panel: Add R61505 panel support
>   video: panel: Add R61517 panel support
>   video: display: Add VGA Digital to Analog Converter support
>   video: display: Add VGA connector support
>   ARM: shmobile: r8a7790: Add DU clocks for DT
>   ARM: shmobile: r8a7790: Add DU device node to device tree
>   ARM: shmobile: marzen: Port DU platform data to CDF
>   ARM: shmobile: lager: Port DU platform data to CDF
>   ARM: shmobile: lager-reference: Add display device nodes to device
>     tree
>   drm/rcar-du: Port to the Common Display Framework
>
>  arch/arm/boot/dts/r8a7790-lager-reference.dts |  92 ++++
>  arch/arm/boot/dts/r8a7790.dtsi                |  33 ++
>  arch/arm/mach-shmobile/board-lager.c          |  76 ++-
>  arch/arm/mach-shmobile/board-marzen.c         |  77 ++-
>  arch/arm/mach-shmobile/clock-r8a7790.c        |   5 +
>  drivers/gpu/drm/rcar-du/Kconfig               |   3 +-
>  drivers/gpu/drm/rcar-du/Makefile              |   7 +-
>  drivers/gpu/drm/rcar-du/rcar_du_connector.c   | 164 ++++++
>  drivers/gpu/drm/rcar-du/rcar_du_connector.h   |  36 ++
>  drivers/gpu/drm/rcar-du/rcar_du_crtc.h        |   2 +-
>  drivers/gpu/drm/rcar-du/rcar_du_drv.c         | 279 ++++++++--
>  drivers/gpu/drm/rcar-du/rcar_du_drv.h         |  28 +-
>  drivers/gpu/drm/rcar-du/rcar_du_encoder.c     |  87 ++-
>  drivers/gpu/drm/rcar-du/rcar_du_encoder.h     |  22 +-
>  drivers/gpu/drm/rcar-du/rcar_du_kms.c         | 116 +++-
>  drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c     | 131 -----
>  drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h     |  25 -
>  drivers/gpu/drm/rcar-du/rcar_du_vgacon.c      |  96 ----
>  drivers/gpu/drm/rcar-du/rcar_du_vgacon.h      |  23 -
>  drivers/video/Kconfig                         |   1 +
>  drivers/video/Makefile                        |   1 +
>  drivers/video/display/Kconfig                 |  62 +++
>  drivers/video/display/Makefile                |   9 +
>  drivers/video/display/con-vga.c               | 148 +++++
>  drivers/video/display/display-core.c          | 759 ++++++++++++++++++++++++++
>  drivers/video/display/display-notifier.c      | 542 ++++++++++++++++++
>  drivers/video/display/mipi-dbi-bus.c          | 234 ++++++++
>  drivers/video/display/panel-dpi.c             | 207 +++++++
>  drivers/video/display/panel-r61505.c          | 567 +++++++++++++++++++
>  drivers/video/display/panel-r61517.c          | 460 ++++++++++++++++
>  drivers/video/display/vga-dac.c               | 152 ++++++
>  drivers/video/omap2/displays-new/Kconfig      |  24 +-
>  drivers/video/omap2/displays-new/Makefile     |  24 +-
>  include/linux/platform_data/rcar-du.h         |  55 +-
>  include/video/display.h                       | 398 ++++++++++++++
>  include/video/mipi-dbi-bus.h                  | 125 +++++
>  include/video/panel-dpi.h                     |  24 +
>  include/video/panel-r61505.h                  |  27 +
>  include/video/panel-r61517.h                  |  28 +
>  39 files changed, 4615 insertions(+), 534 deletions(-)
>  create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_connector.c
>  create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_connector.h
>  delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
>  delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_lvdscon.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/video/display/Kconfig
>  create mode 100644 drivers/video/display/Makefile
>  create mode 100644 drivers/video/display/con-vga.c
>  create mode 100644 drivers/video/display/display-core.c
>  create mode 100644 drivers/video/display/display-notifier.c
>  create mode 100644 drivers/video/display/mipi-dbi-bus.c
>  create mode 100644 drivers/video/display/panel-dpi.c
>  create mode 100644 drivers/video/display/panel-r61505.c
>  create mode 100644 drivers/video/display/panel-r61517.c
>  create mode 100644 drivers/video/display/vga-dac.c
>  create mode 100644 include/video/display.h
>  create mode 100644 include/video/mipi-dbi-bus.h
>  create mode 100644 include/video/panel-dpi.h
>  create mode 100644 include/video/panel-r61505.h
>  create mode 100644 include/video/panel-r61517.h
>
> --
> Regards,
>
> Laurent Pinchart
>

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 08/19] video: display: Add MIPI DBI bus support
  2013-08-09 17:14 ` [PATCH/RFC v3 08/19] video: display: Add MIPI DBI bus support Laurent Pinchart
@ 2013-08-14  0:52   ` Rob Clark
  2013-08-20 13:26     ` Laurent Pinchart
  2013-08-26 11:10   ` Tomi Valkeinen
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 83+ messages in thread
From: Rob Clark @ 2013-08-14  0:52 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-fbdev, Sebastien Guiriec, dri-devel, Jesse Barnes,
	Benjamin Gaignard, Tom Gall, Ragesh Radhakrishnan,
	Tomi Valkeinen, linux-media, Stephen Warren, Mark Zhang,
	Stéphane Marchesin, Alexandre Courbot, Thomas Petazzoni,
	Sunil Joshi, Kyungmin Park, Maxime Ripard, Vikas Sajjan,
	Marcus Lorentzon

On Fri, Aug 9, 2013 at 1:14 PM, Laurent Pinchart
<laurent.pinchart+renesas@ideasonboard.com> wrote:
> MIPI DBI is a configurable-width parallel display bus that transmits
> commands and data.
>
> Add a new DBI Linux bus type that implements the usual bus
> infrastructure (including devices and drivers (un)registration and
> matching, and bus configuration and access functions).
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/video/display/Kconfig        |   8 ++
>  drivers/video/display/Makefile       |   1 +
>  drivers/video/display/mipi-dbi-bus.c | 234 +++++++++++++++++++++++++++++++++++
>  include/video/display.h              |   4 +
>  include/video/mipi-dbi-bus.h         | 125 +++++++++++++++++++
>  5 files changed, 372 insertions(+)
>  create mode 100644 drivers/video/display/mipi-dbi-bus.c
>  create mode 100644 include/video/mipi-dbi-bus.h
>
> diff --git a/drivers/video/display/Kconfig b/drivers/video/display/Kconfig
> index 1d533e7..f7532c1 100644
> --- a/drivers/video/display/Kconfig
> +++ b/drivers/video/display/Kconfig
> @@ -2,3 +2,11 @@ menuconfig DISPLAY_CORE
>         tristate "Display Core"
>         ---help---
>           Support common display framework for graphics devices.
> +
> +if DISPLAY_CORE
> +
> +config DISPLAY_MIPI_DBI
> +       tristate
> +       default n
> +
> +endif # DISPLAY_CORE
> diff --git a/drivers/video/display/Makefile b/drivers/video/display/Makefile
> index b907aad..59022d2 100644
> --- a/drivers/video/display/Makefile
> +++ b/drivers/video/display/Makefile
> @@ -1,3 +1,4 @@
>  display-y                                      := display-core.o \
>                                                    display-notifier.o
>  obj-$(CONFIG_DISPLAY_CORE)                     += display.o
> +obj-$(CONFIG_DISPLAY_MIPI_DBI)                 += mipi-dbi-bus.o
> diff --git a/drivers/video/display/mipi-dbi-bus.c b/drivers/video/display/mipi-dbi-bus.c
> new file mode 100644
> index 0000000..791fb4d
> --- /dev/null
> +++ b/drivers/video/display/mipi-dbi-bus.c
> @@ -0,0 +1,234 @@
> +/*
> + * MIPI DBI Bus
> + *
> + * Copyright (C) 2012 Renesas Solutions Corp.
> + *
> + * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> + *
> + * 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.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/export.h>
> +#include <linux/kernel.h>
> +#include <linux/list.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/pm.h>
> +#include <linux/pm_runtime.h>
> +
> +#include <video/mipi-dbi-bus.h>
> +
> +/* -----------------------------------------------------------------------------
> + * Bus operations
> + */
> +
> +int mipi_dbi_set_data_width(struct mipi_dbi_device *dev, unsigned int width)
> +{
> +       if (width != 8 && width != 16)
> +               return -EINVAL;
> +
> +       dev->data_width = width;
> +       return 0;
> +}
> +EXPORT_SYMBOL_GPL(mipi_dbi_set_data_width);
> +
> +int mipi_dbi_write_command(struct mipi_dbi_device *dev, u16 cmd)
> +{
> +       return dev->bus->ops->write_command(dev->bus, dev, cmd);
> +}
> +EXPORT_SYMBOL_GPL(mipi_dbi_write_command);
> +
> +int mipi_dbi_write_data(struct mipi_dbi_device *dev, const u8 *data,
> +                       size_t len)
> +{
> +       return dev->bus->ops->write_data(dev->bus, dev, data, len);
> +}
> +EXPORT_SYMBOL_GPL(mipi_dbi_write_data);
> +
> +int mipi_dbi_read_data(struct mipi_dbi_device *dev, u8 *data, size_t len)
> +{
> +       return dev->bus->ops->read_data(dev->bus, dev, data, len);
> +}
> +EXPORT_SYMBOL_GPL(mipi_dbi_read_data);
> +
> +/* -----------------------------------------------------------------------------
> + * Bus type
> + */
> +
> +static const struct mipi_dbi_device_id *
> +mipi_dbi_match_id(const struct mipi_dbi_device_id *id,
> +                 struct mipi_dbi_device *dev)
> +{
> +       while (id->name[0]) {
> +               if (strcmp(dev->name, id->name) == 0) {
> +                       dev->id_entry = id;
> +                       return id;
> +               }
> +               id++;
> +       }
> +       return NULL;
> +}
> +
> +static int mipi_dbi_match(struct device *_dev, struct device_driver *_drv)
> +{
> +       struct mipi_dbi_device *dev = to_mipi_dbi_device(_dev);
> +       struct mipi_dbi_driver *drv = to_mipi_dbi_driver(_drv);
> +
> +       if (drv->id_table)
> +               return mipi_dbi_match_id(drv->id_table, dev) != NULL;
> +
> +       return (strcmp(dev->name, _drv->name) == 0);
> +}
> +
> +static ssize_t modalias_show(struct device *_dev, struct device_attribute *a,
> +                            char *buf)
> +{
> +       struct mipi_dbi_device *dev = to_mipi_dbi_device(_dev);
> +       int len = snprintf(buf, PAGE_SIZE, MIPI_DBI_MODULE_PREFIX "%s\n",
> +                          dev->name);
> +
> +       return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
> +}
> +
> +static struct device_attribute mipi_dbi_dev_attrs[] = {
> +       __ATTR_RO(modalias),
> +       __ATTR_NULL,
> +};
> +
> +static int mipi_dbi_uevent(struct device *_dev, struct kobj_uevent_env *env)
> +{
> +       struct mipi_dbi_device *dev = to_mipi_dbi_device(_dev);
> +
> +       add_uevent_var(env, "MODALIAS=%s%s", MIPI_DBI_MODULE_PREFIX,
> +                      dev->name);
> +       return 0;
> +}
> +
> +static const struct dev_pm_ops mipi_dbi_dev_pm_ops = {
> +       .runtime_suspend = pm_generic_runtime_suspend,
> +       .runtime_resume = pm_generic_runtime_resume,
> +       .suspend = pm_generic_suspend,
> +       .resume = pm_generic_resume,
> +       .freeze = pm_generic_freeze,
> +       .thaw = pm_generic_thaw,
> +       .poweroff = pm_generic_poweroff,
> +       .restore = pm_generic_restore,
> +};
> +
> +static struct bus_type mipi_dbi_bus_type = {
> +       .name           = "mipi-dbi",
> +       .dev_attrs      = mipi_dbi_dev_attrs,
> +       .match          = mipi_dbi_match,
> +       .uevent         = mipi_dbi_uevent,
> +       .pm             = &mipi_dbi_dev_pm_ops,
> +};
> +
> +/* -----------------------------------------------------------------------------
> + * Device and driver (un)registration
> + */
> +
> +/**
> + * mipi_dbi_device_register - register a DBI device
> + * @dev: DBI device we're registering
> + */
> +int mipi_dbi_device_register(struct mipi_dbi_device *dev,
> +                             struct mipi_dbi_bus *bus)
> +{
> +       device_initialize(&dev->dev);
> +
> +       dev->bus = bus;
> +       dev->dev.bus = &mipi_dbi_bus_type;
> +       dev->dev.parent = bus->dev;
> +
> +       if (dev->id != -1)
> +               dev_set_name(&dev->dev, "%s.%d", dev->name,  dev->id);
> +       else
> +               dev_set_name(&dev->dev, "%s", dev->name);
> +
> +       return device_add(&dev->dev);
> +}
> +EXPORT_SYMBOL_GPL(mipi_dbi_device_register);
> +
> +/**
> + * mipi_dbi_device_unregister - unregister a DBI device
> + * @dev: DBI device we're unregistering
> + */
> +void mipi_dbi_device_unregister(struct mipi_dbi_device *dev)
> +{
> +       device_del(&dev->dev);
> +       put_device(&dev->dev);
> +}
> +EXPORT_SYMBOL_GPL(mipi_dbi_device_unregister);
> +
> +static int mipi_dbi_drv_probe(struct device *_dev)
> +{
> +       struct mipi_dbi_driver *drv = to_mipi_dbi_driver(_dev->driver);
> +       struct mipi_dbi_device *dev = to_mipi_dbi_device(_dev);
> +
> +       return drv->probe(dev);
> +}
> +
> +static int mipi_dbi_drv_remove(struct device *_dev)
> +{
> +       struct mipi_dbi_driver *drv = to_mipi_dbi_driver(_dev->driver);
> +       struct mipi_dbi_device *dev = to_mipi_dbi_device(_dev);
> +       int ret;
> +
> +       ret = drv->remove(dev);
> +       if (ret < 0)
> +               return ret;
> +
> +       mipi_dbi_set_drvdata(dev, NULL);
> +
> +       return 0;
> +}
> +
> +/**
> + * mipi_dbi_driver_register - register a driver for DBI devices
> + * @drv: DBI driver structure
> + */
> +int mipi_dbi_driver_register(struct mipi_dbi_driver *drv)
> +{
> +       drv->driver.bus = &mipi_dbi_bus_type;
> +       if (drv->probe)
> +               drv->driver.probe = mipi_dbi_drv_probe;
> +       if (drv->remove)
> +               drv->driver.remove = mipi_dbi_drv_remove;
> +
> +       return driver_register(&drv->driver);
> +}
> +EXPORT_SYMBOL_GPL(mipi_dbi_driver_register);
> +
> +/**
> + * mipi_dbi_driver_unregister - unregister a driver for DBI devices
> + * @drv: DBI driver structure
> + */
> +void mipi_dbi_driver_unregister(struct mipi_dbi_driver *drv)
> +{
> +       driver_unregister(&drv->driver);
> +}
> +EXPORT_SYMBOL_GPL(mipi_dbi_driver_unregister);
> +
> +/* -----------------------------------------------------------------------------
> + * Init/exit
> + */
> +
> +static int __init mipi_dbi_init(void)
> +{
> +       return bus_register(&mipi_dbi_bus_type);
> +}
> +
> +static void __exit mipi_dbi_exit(void)
> +{
> +       bus_unregister(&mipi_dbi_bus_type);
> +}
> +
> +module_init(mipi_dbi_init);
> +module_exit(mipi_dbi_exit)
> +
> +MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
> +MODULE_DESCRIPTION("MIPI DBI Bus");
> +MODULE_LICENSE("GPL");
> diff --git a/include/video/display.h b/include/video/display.h
> index ba319d6..3138401 100644
> --- a/include/video/display.h
> +++ b/include/video/display.h
> @@ -17,6 +17,7 @@
>  #include <linux/list.h>
>  #include <linux/module.h>
>  #include <media/media-entity.h>
> +#include <video/mipi-dbi-bus.h>
>
>  #define DISPLAY_PIXEL_CODING(option, type, from, to, variant) \
>         (((option) << 17) | ((type) << 13) | ((variant) << 10) | \
> @@ -189,6 +190,9 @@ enum display_entity_interface_type {
>
>  struct display_entity_interface_params {
>         enum display_entity_interface_type type;
> +       union {
> +               struct mipi_dbi_interface_params dbi;
> +       } p;
>  };
>
>  struct display_entity_control_ops {
> diff --git a/include/video/mipi-dbi-bus.h b/include/video/mipi-dbi-bus.h
> new file mode 100644
> index 0000000..876b69d
> --- /dev/null
> +++ b/include/video/mipi-dbi-bus.h
> @@ -0,0 +1,125 @@
> +/*
> + * MIPI DBI Bus
> + *
> + * Copyright (C) 2012 Renesas Solutions Corp.
> + *
> + * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> + *
> + * 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.
> + */
> +
> +#ifndef __MIPI_DBI_BUS_H__
> +#define __MIPI_DBI_BUS_H__
> +
> +#include <linux/device.h>
> +
> +struct mipi_dbi_bus;
> +struct mipi_dbi_device;
> +
> +struct mipi_dbi_bus_ops {
> +       int (*write_command)(struct mipi_dbi_bus *bus,
> +                            struct mipi_dbi_device *dev, u16 cmd);
> +       int (*write_data)(struct mipi_dbi_bus *bus, struct mipi_dbi_device *dev,
> +                         const u8 *data, size_t len);
> +       int (*read_data)(struct mipi_dbi_bus *bus, struct mipi_dbi_device *dev,
> +                        u8 *data, size_t len);
> +};
> +
> +struct mipi_dbi_bus {
> +       struct device *dev;
> +       const struct mipi_dbi_bus_ops *ops;
> +};
> +
> +#define MIPI_DBI_MODULE_PREFIX         "mipi-dbi:"
> +#define MIPI_DBI_NAME_SIZE             32
> +
> +struct mipi_dbi_device_id {
> +       char name[MIPI_DBI_NAME_SIZE];
> +       __kernel_ulong_t driver_data    /* Data private to the driver */
> +                       __aligned(sizeof(__kernel_ulong_t));
> +};
> +
> +enum mipi_dbi_interface_type {
> +       MIPI_DBI_INTERFACE_TYPE_A,
> +       MIPI_DBI_INTERFACE_TYPE_B,
> +};
> +
> +#define MIPI_DBI_INTERFACE_TE          (1 << 0)
> +
> +struct mipi_dbi_interface_params {
> +       enum mipi_dbi_interface_type type;
> +       unsigned int flags;
> +
> +       unsigned int cs_setup;
> +       unsigned int rd_setup;
> +       unsigned int rd_latch;
> +       unsigned int rd_cycle;
> +       unsigned int rd_hold;
> +       unsigned int wr_setup;
> +       unsigned int wr_cycle;
> +       unsigned int wr_hold;
> +};
> +
> +#define MIPI_DBI_FLAG_ALIGN_LEFT       (1 << 0)
> +
> +struct mipi_dbi_device {
> +       const char *name;
> +       int id;
> +       struct device dev;

just fwiw, we need the "framework" to be agnostic of the association
between devices and entities in the framework.  Some things that are
multiple entities may actually map to a single device in hw (and
possibly visa versa?).  Otherwise we end up having to create fake
devices in some cases.  Really the entities, or objects, or whatever
you call 'em should just extend some kref'd base class.  Sort of like
how existing kms objects extend drm_mode_object.

So any 'struct device' moves down into the derived class, not in the
base class.  Configuration data is passed in separate, not grabbed out
of dev->platform_data, etc.  Probably there is room for some helpers
to pull stuff out of DT/ACPI/whatever.

BR,
-R

> +       const struct mipi_dbi_device_id *id_entry;
> +       struct mipi_dbi_bus *bus;
> +
> +       unsigned int flags;
> +       unsigned int bus_width;
> +       unsigned int data_width;
> +};
> +
> +#define to_mipi_dbi_device(d)  container_of(d, struct mipi_dbi_device, dev)
> +
> +int mipi_dbi_device_register(struct mipi_dbi_device *dev,
> +                            struct mipi_dbi_bus *bus);
> +void mipi_dbi_device_unregister(struct mipi_dbi_device *dev);
> +
> +struct mipi_dbi_driver {
> +       int(*probe)(struct mipi_dbi_device *);
> +       int(*remove)(struct mipi_dbi_device *);
> +       struct device_driver driver;
> +       const struct mipi_dbi_device_id *id_table;
> +};
> +
> +#define to_mipi_dbi_driver(d)  container_of(d, struct mipi_dbi_driver, driver)
> +
> +int mipi_dbi_driver_register(struct mipi_dbi_driver *drv);
> +void mipi_dbi_driver_unregister(struct mipi_dbi_driver *drv);
> +
> +static inline void *mipi_dbi_get_drvdata(const struct mipi_dbi_device *dev)
> +{
> +       return dev_get_drvdata(&dev->dev);
> +}
> +
> +static inline void mipi_dbi_set_drvdata(struct mipi_dbi_device *dev,
> +                                       void *data)
> +{
> +       dev_set_drvdata(&dev->dev, data);
> +}
> +
> +/* module_mipi_dbi_driver() - Helper macro for drivers that don't do
> + * anything special in module init/exit.  This eliminates a lot of
> + * boilerplate.  Each module may only use this macro once, and
> + * calling it replaces module_init() and module_exit()
> + */
> +#define module_mipi_dbi_driver(__mipi_dbi_driver) \
> +       module_driver(__mipi_dbi_driver, mipi_dbi_driver_register, \
> +                       mipi_dbi_driver_unregister)
> +
> +int mipi_dbi_set_data_width(struct mipi_dbi_device *dev, unsigned int width);
> +
> +int mipi_dbi_write_command(struct mipi_dbi_device *dev, u16 cmd);
> +int mipi_dbi_read_data(struct mipi_dbi_device *dev, u8 *data, size_t len);
> +int mipi_dbi_write_data(struct mipi_dbi_device *dev, const u8 *data,
> +                       size_t len);
> +
> +#endif /* __MIPI_DBI_BUS__ */
> --
> 1.8.1.5
>

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 08/19] video: display: Add MIPI DBI bus support
  2013-08-14  0:52   ` Rob Clark
@ 2013-08-20 13:26     ` Laurent Pinchart
  0 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2013-08-20 13:26 UTC (permalink / raw)
  To: Rob Clark
  Cc: linux-fbdev, Benjamin Gaignard, dri-devel, Jesse Barnes,
	Sebastien Guiriec, Laurent Pinchart, Tom Gall,
	Ragesh Radhakrishnan, Tomi Valkeinen, linux-media,
	Stephen Warren, Mark Zhang, Stéphane Marchesin,
	Alexandre Courbot, Thomas Petazzoni, Sunil Joshi, Kyungmin Park,
	Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

Hi Rob,

On Tuesday 13 August 2013 20:52:15 Rob Clark wrote:
> On Fri, Aug 9, 2013 at 1:14 PM, Laurent Pinchart wrote:
> > MIPI DBI is a configurable-width parallel display bus that transmits
> > commands and data.
> > 
> > Add a new DBI Linux bus type that implements the usual bus
> > infrastructure (including devices and drivers (un)registration and
> > matching, and bus configuration and access functions).
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> > 
> >  drivers/video/display/Kconfig        |   8 ++
> >  drivers/video/display/Makefile       |   1 +
> >  drivers/video/display/mipi-dbi-bus.c | 234 ++++++++++++++++++++++++++++++
> >  include/video/display.h              |   4 +
> >  include/video/mipi-dbi-bus.h         | 125 +++++++++++++++++++
> >  5 files changed, 372 insertions(+)
> >  create mode 100644 drivers/video/display/mipi-dbi-bus.c
> >  create mode 100644 include/video/mipi-dbi-bus.h

[snip]

> > diff --git a/include/video/mipi-dbi-bus.h b/include/video/mipi-dbi-bus.h
> > new file mode 100644
> > index 0000000..876b69d
> > --- /dev/null
> > +++ b/include/video/mipi-dbi-bus.h

[snip]

> > +struct mipi_dbi_device {
> > +       const char *name;
> > +       int id;
> > +       struct device dev;
> 
> just fwiw, we need the "framework" to be agnostic of the association between
> devices and entities in the framework. Some things that are multiple
> entities may actually map to a single device in hw

I haven't written down that requirement, but I've kept it in mind while 
designing CDF. We have similar use cases in V4L2.

> (and possibly visa versa?).

I don't think that would be needed, but if you can think of a use case I'm all 
ears.

> Otherwise we end up having to create fake devices in some cases. Really the
> entities, or objects, or whatever you call 'em should just extend some
> kref'd base class. Sort of like how existing kms objects extend
> drm_mode_object.

struct display_entity {
        struct list_head list;
        struct device *dev;
        struct module *owner;
        struct kref ref;

        char name[32];
        struct media_entity entity;

        const struct display_entity_ops *ops;

        void(*release)(struct display_entity *ent);
};

(from patch 02/19)

> So any 'struct device' moves down into the derived class, not in the base
> class. Configuration data is passed in separate, not grabbed out of dev->
> platform_data, etc. Probably there is room for some helpers to pull stuff
> out of DT/ACPI/whatever.

struct mipi_dbi_device is not a display entity, it's a physical device plugged 
on a DBI bus. It's thus similar in purpose to struct pci_device or struct 
platform_device. The DBI device driver will then create one or more display 
entities depending on its needs.

> > +       const struct mipi_dbi_device_id *id_entry;
> > +       struct mipi_dbi_bus *bus;
> > +
> > +       unsigned int flags;
> > +       unsigned int bus_width;
> > +       unsigned int data_width;
> > +};

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
  2013-08-14  0:43 ` [PATCH/RFC v3 00/19] " Rob Clark
@ 2013-08-20 15:24   ` Laurent Pinchart
  2013-08-20 18:40     ` Rob Clark
  0 siblings, 1 reply; 83+ messages in thread
From: Laurent Pinchart @ 2013-08-20 15:24 UTC (permalink / raw)
  To: Rob Clark
  Cc: linux-fbdev, Benjamin Gaignard, dri-devel, Jesse Barnes,
	Sebastien Guiriec, Laurent Pinchart, Tom Gall,
	Ragesh Radhakrishnan, Tomi Valkeinen, linux-media,
	Stephen Warren, Mark Zhang, Stéphane Marchesin,
	Alexandre Courbot, Thomas Petazzoni, Sunil Joshi, Kyungmin Park,
	Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

Hi Rob,

On Tuesday 13 August 2013 20:43:50 Rob Clark wrote:
> On Fri, Aug 9, 2013 at 1:14 PM, Laurent Pinchart wrote:
> > Hi everybody,
> > 
> > Here's the third RFC of the Common Display Framework.
> > 
> > I won't repeat all the background information from the versions one and
> > two here, you can read it at http://lwn.net/Articles/512363/ and
> > http://lwn.net/Articles/526965/.
> > 
> > This RFC isn't final. Given the high interest in CDF and the urgent tasks
> > that kept delaying the next version of the patch set, I've decided to
> > release v3 before completing all parts of the implementation. Known
> > missing items are
> > 
> > - documentation: kerneldoc and this cover letter should provide basic
> >   information, more extensive documentation will likely make it to v4.
> > 
> > - pipeline configuration and control: generic code to configure and
> >   control display pipelines (in a nutshell, translating high-level mode
> >   setting and DPMS calls to low-level entity operations) is missing. Video
> >   and stream control operations have been carried over from v2, but will
> >   need to be revised for v4.
> > 
> > - DSI support: I still have no DSI hardware I can easily test the code on.
> 
> tbh, I kinda think that DSI and bridge chips are the things we should focus
> on first.. that seems what is most important for current and new hardware. 
> Back-filling to handle older/simpler panels can be done later.

That sounds reasonable (although I still believe DSI is only part of the 
issue), but I'll need help with that, as the Renesas platforms I work on don't 
have a DSI bus.

> > Special thanks go to
> > 
> > - Renesas for inviting me to LinuxCon Japan 2013 where I had the
> >   opportunity to validate the CDF v3 concepts with Alexandre Courbot
> >   (NVidia) and Tomasz Figa (Samsung).
> > 
> > - Tomi Valkeinen (TI) for taking the time to deeply brainstorm v3 with me.
> > 
> > - Linaro for inviting me to Linaro Connect Europe 2013, the discussions we
> >   had  there greatly helped moving CDF forward.
> > 
> > - And of course all the developers who showed interest in CDF and spent
> >   time sharing ideas, reviewing patches and testing code.
> > 
> > I have to confess I was a bit lost and discouraged after all the CDF-
> > related meetings during which we have discussed how to move from v2 to v3.
> > With every meeting I was hoping to run the implementation through use
> > cases of various interesting parties and narrow down the scope of the huge
> > fuzzy beast that CDF was. With every meeting the scope actually broadened,
> > with no clear path at sight anywhere.
> > 
> > Earlier this year I was about to drop one of the requirements on which I
> > had based CDF v2: sharing drivers between DRM/KMS and V4L2. With only two
> > HDMI transmitters as use cases for that feature (with only out-of-tree
> > drivers so far), I just thought the involved completely wasn't worth it
> > and that I should implement CDF v3 as a DRM/KMS-only helper framework.
> > However, a seemingly unrelated discussion with Xilinx developers showed
> > me that hybrid SoC-FPGA platforms such as the Xilinx Zynq 7000 have a
> > larger library of IP cores that can be used in camera capture pipelines
> > and in display pipelines. The two use cases suddenly became tens or even
> > hundreds of use cases that I couldn't ignore anymore.
> 
> Hmm, I'm still not really convinced ;-)
> 
> Or maybe, put another way, I still think we should still optimize for the
> common case. I mean I'm sure you *can* design hw that has an LVDS->DP bridge
> in the capture path, and if you had something like an FPGA where that was
> cheap to do maybe you even would (for fun). But if in the real world, there
> are only one or two cases of actual hw using the same bridge in a capture
> pipeline which is normally used in display pipelines, then duplicating some
> small bit of code for that abnormal case if it makes things easier for the
> common case, seems like a reasonable trade-off to me.

That was my opinion as well until I started working on a Xilinx platform. 
There's dozens of IP cores there that are used in both capture and display 
pipelines.

Furthermore, FPGA display pipelines being made of individual IP cores, we need 
a way to write one driver per IP core and make them all interact. The recently 
proposed drm_bridge is one possible solution to this issue (and to a different 
but similar issue that trigerred the development of drm_bridge), but it's in 
my opinion not generic enough. We're facing several problems that are related, 
it would really be a shame not to solve them with a good enough framework.

> I mean, take a DSI panel driver, for example.. anything but a trivial panel
> driver, you are going to want to expose some custom properties on the
> connector for controlling non-standard features. So you end up with both
> cdf_foo for the common part, and drm_foo for gluing in the properties. And
> now these two parts which otherwise would be one, end up having to stay in
> sync merged through different trees, etc. It seems a lot like making my life
> more difficult for a fairly hypothetical gain ;-)

The DSI panel driver should not be split into two parts. It should implement a 
CDF entity, any glue needed for DRM will not be part of the panel driver.

> Or, take an hdmi or DP bridge. To use any of the common
> infrastructure/helpers in drm, you end up implementing a generic interface,
> where both the producer and consumer is inside drm. Which just seems a bit
> pointless and extra hoops to jump through. Especially when we discover that
> we need to extend/enhance the common interface outside of drm to make it
> work. (I'm thinking of display_entity_control_ops::get_modes() here, but I'm
> sure there are more examples.) And I think we'll run into similar issues
> with display_entity_control_ops::set_state(), since the on<->off sequencing
> can get hairy when the upstream/downstream entity is fed a clk by the
> downstream/upstream entity. And similarly, I think we'll go through a few
> revisions of DSI panel/bus params before we have everything that everyone
> needs.

I don't see where needing multiple revisions of a patch set would be bad :-)

> (Don't get me wrong.. if we were starting from scratch, I'd tend to think
> that stuff downstream of the crtc should share common framework w/ v4l.. but
> we are pretty far from starting from scratch, and how to get from where we
> are today to future is just as important as the end result.)

Then let's discuss how to get there. We have issues we need to solve, and we 
need a new framework for that. There's no way to share panel drivers today, no 
way to design DT bindings for them, no way to avoid duplicating dozens of IP 
core drivers in FPGAs, no way to support chained encoders (as shown by the 
drm_bridge proposal). All those problems must be solved now, not in a couple 
of years. The window of opportunity is here, and I don't want to waste it.

> > CDF v3 is thus userspace API agnostic. It isn't tied to DRM/KMS or V4L2
> > and can be used by any kernel subsystem, potentially including FBDEV
> > (although I won't personally wrote FBDEV support code, as I've already
> > advocated for FBDEV to be deprecated).
> > 
> > The code you are about to read is based on the concept of display entities
> > introduced in v2. Diagrams related to the explanations below are available
> > at http://ideasonboard.org/media/cdf/20130709-lce-cdf.pdf.
> > 
> > 
> > Display Entities
> > ----------------
> > 
> > A display entity abstracts any hardware block that sources, processes or
> > sinks display-related video streams. It offers an abstract API,
> > implemented by display entity drivers, that is used by master drivers
> > (such as the main display driver) to query, configure and control display
> > pipelines.
> > 
> > Display entities are connected to at least one video data bus, and
> > optionally to a control bus. The video data busses carry display-related
> > video data out of sources (such as a CRTC in a display controller) to
> > sinks (such as a panel or a monitor), optionally going through
> > transmitters, encoders, decoders, bridges or other similar devices. A
> > CRTC or a panel will usually be connected to a single data bus, while an
> > encoder or a transmitter will be connected to two data busses.
> > 
> > The simple linear display pipelines we find in most embedded platforms at
> > the moment are expected to grow more complex with time. CDF needs to
> > accomodate those needs from the start to be, if not future-proof, at
> > least present-proof at the time it will get merged in to mainline. For
> > this reason display entities have data ports through which video streams
> > flow in or out, with link objects representing the connections between
> > those ports. A typical entity in a linear display pipeline will have one
> > (for video source and video sink entities such as CRTCs or panels) or two
> > ports (for video processing entities such as encoders), but more ports
> > are allowed, and entities can be linked in complex non-linear pipelines.
> > 
> > Readers might think that this model if extremely similar to the media
> > controller graph model. They would be right, and given my background this
> > is most probably not a coincidence. The CDF v3 implementation uses the
> > in-kernel media controller framework to model the graph of display
> > entities, with the display entity data structure inheriting from the
> > media entity structure. The display pipeline graph topology will be
> > automatically exposed to userspace through the media controller API as an
> > added bonus. However, ussage of the media controller userspace API in
> > applications is *not* mandatory, and the current CDF implementation
> > doesn't use the media controller link setup userspace API to configure
> > the display pipelines.
> > 
> > While some display entities don't require any configuration (DPI panels
> > are a good example), many of them are connected to a control bus
> > accessible to the CPU. Control requests can be sent on a dedicated
> > control bus (such as I2C or SPI) or multiplexed on a mixed control and
> > data bus (such as DBI or DSI). To support both options the CDF display
> > entity model separates the control and data busses in different APIs.
> > 
> > Display entities are abstract object that must be implemented by a real
> > device. The device sits on its control bus and is registered with the
> > Linux
> > device core and matched with his driver using the control bus specific
> > API.
> > The CDF doesn't create a display entity class or bus, display entity
> > drivers thus standard Linux kernel drivers using existing busses. A DBI
> > bus is added as part of this patch set, but strictly speaking this isn't
> > part of CDF.
> > 
> > When a display entity driver probes a device it must create an instance of
> > the display_entity structure, initialize it and add it to the CDF core
> > entities pool. The display entity exposes abstract operations through
> > function pointers, and the entity driver must implement those operations.
> > Those operations can act on either the whole entity or on a given port,
> > depending on the operation. They are divided in two groups, control
> > operations and video operations.
> > 
> > 
> > Control Operations
> > ------------------
> > 
> > Control operations are called by upper-level drivers, usually in response
> > to a request originating from userspace. They query or control the
> > display entity state and operation. Currently defined control operations
> > are
> > 
> > - get_size(), to retrieve the entity physical size (applicable to panels
> > only) - get_modes(), to retrieve the video modes supported at an entity
> > port - get_params(), to retrieve the data bus parameters at an entity
> > port
> > 
> > - set_state(), to control the state of the entity (off, standby or on)
> > - update(), to trigger a display update (for entities that implement
> > manual
> > 
> >   update, such as manual-update panels that store frames in their internal
> >   frame buffer)
> > 
> > The last two operations have been carried from v2 and will be reworked.
> > 
> > 
> > Pipeline Control
> > ----------------
> > 
> > The figure on page 4 shows the control model for a linear pipeline. This
> > differs significantly from CDF v2 where calls where forwarded from entity
> > to entity using a Russian dolls model. v3 removes the need of neighbour
> > awareness from entity drivers, simplifying the entity drivers. The
> > complexity of pipeline configuration is moved to a central location
> > called a pipeline controller instead of being spread out to all drivers.
> > 
> > Pipeline controllers provide library functions that display drivers can
> > use to control a pipeline. Several controllers can be implemented to
> > accomodate the needs of various pipeline topologies and complexities, and
> > display drivers can even implement their own pipeline control algorithm
> > if needed. I'm working on a linear pipeline controller for the next
> > version of the patch set.
> > 
> > If pipeline controllers are responsible for propagating a pipeline
> > configuration on all entity ports in the pipeline, entity drivers are
> > responsible for propagating the configuration inside entities, from sink
> > (input) to source (output) ports as illustrated on page 5. The rationale
> > behind this is that knowledge of the entity internals is located in the
> > entity driver, while knowledge of the pipeline belongs to the pipeline
> > controller. The controller will thus configure the pipeline by performing
> > the following steps:
> > 
> > - applying a configuration on sink ports of an entity
> > - read the configuration that has been propagated by the entity driver on
> > its> 
> >   source ports
> > 
> > - optionally, modify the source port configuration (to configure custom
> > timings,> 
> >   scaling or other parameters, if supported by the entity)
> > 
> > - propagate the source port configuration to the sink ports of the next
> > entities> 
> >   in the pipeline and start over
> > 
> > Beside modifying the active configuration, the entities API will allow
> > trying configurations without applying them to the hardware. As
> > configuration of a port possibly depend on the configurations of the
> > other ports, trying a configuration must be done at the entity level
> > instead of the port level. The implementation will be based on the
> > concept of configuration store objects that will store the configuration
> > of all ports for a given entity. Each entity will have a single active
> > configuration store, and test configuration stores will be created
> > dynamically to try a configuration on an entity. The get and set
> > operations implemented by the entity will receive a configuration store
> > pointer, and active and test code paths in entity drivers will be
> > identical, except for applying the configuration to the hardware for the
> > active code path.
> > 
> > 
> > Video Operations
> > ----------------
> > 
> > Video operations control the video stream state on entity ports. The only
> > currently defined video operation is
> > 
> > - set_stream(), to start (in continuous or single-shot mode) the video
> > stream> 
> >   on an entity port
> > 
> > The call model for video operations differ from the control operations
> > model described above. The set_stream() operation is called directly by
> > downstream entities on upstream entities (from a video data bus point of
> > view). Terminating entities in a pipeline (such as panels) will usually
> > call the set_stream() operation in their set_state() handler, and
> > intermediate entities will forward the set_stream() call upstream.
> > 
> > 
> > Integration
> > -----------
> > 
> > The figure on page 8 describes how a panel driver, implemented using CDF
> > as a display entity, interacts with the other components in the system.
> > The use case is a simple pipeline made of a display controller and a
> > panel.
> > 
> > The display controller driver receives control request from userspace
> > through DRM (or FBDEV) API calls. It processes the request and calls the
> > panel driver through the CDF control operations API. The panel driver
> > will then issue requests on its control bus (several possible control
> > busses are shown on the figure, panel drivers typically use one of them
> > only) and call video operations of the display controller on its left
> > side to control the video stream.
> > 
> > 
> > Registration and Notification
> > -----------------------------
> > 
> > Due to possibly complex dependencies between entities we can't guarantee
> > that all entities part of the display pipeline will have been
> > successfully probed when the master display controller driver is probed.
> > For instance a panel can be a child of the DBI or DSI bus controlled by
> > the display device, or use a clock provided by that device. We can't
> > defer the display device probe until the panel is probed and also defer
> > the panel device probe until the display device is probed. For this
> > reason we need a notification system that allows entities to register
> > themselves with the CDF core, and display controller drivers to get
> > notified when entities they need are available.
> > 
> > The notification system has been completely redesigned in v3. This version
> > is based on the V4L2 asynchronous probing notification code, with large
> > parts of the code shamelessly copied. This is an interim solution to let
> > me play with the notification code as needed by CDF. I'm not a fan of
> > code duplication, and will work on merging the CDF and V4L2
> > implementations in a later stage when CDF will reach a mature enough
> > state.
> > 
> > CDF manages a pool of entities and a list of notifiers. Notifiers are
> > registered by master display drivers with an array of entities match
> > descriptors. When an entity is added to the CDF entities pool, all
> > notifiers are searched for a match. If a match is found, the
> > corresponding notifier is called to notify the master display driver.
> > 
> > The two currently supported match methods are platform match, which uses
> > device names, and DT match, which uses DT node pointers. More match method
> > might be added later if needed. Two helper functions exist to build a
> > notifier from a list of platform device names (in the non-DT case) or a
> > DT
> > representation of the display pipeline topology.
> > 
> > Once all required entities have been successfully found, the master
> > display
> > driver is responsible for creating media controller links between all
> > entities in the pipeline. Two helper functions are also available to
> > automate that process, one for the non-DT case and one for the DT case.
> > Once again some DT-related code has been copied from the V4L2 DT code, I
> > will work on merging both in a future version.
> > 
> > Note that notification brings a different issue after registration, as
> > display controller and display entity drivers would take a reference to
> > each other. Those circular references would make driver unloading
> > impossible. One possible solution to this problem would be to simulate an
> > unplug event for the display entity, to force the display driver to
> > release the dislay entities it uses. We would need a userspace API for
> > that though. Better solutions would of course be welcome.
> > 
> > 
> > Device Tree Bindings
> > --------------------
> > 
> > CDF entities device tree bindings are not documented yet. They describe
> > both the graph topology and entity-specific information. The graph
> > description uses the V4L2 DT bindings (which are actually not
> > V4L2-specific) specified at
> > Documentation/devicetree/bindings/media/video-interfaces.txt.
> > Entity-specific information will be described in individual DT bindings
> > documentation. The DPI panel driver uses the display timing bindings
> > documented in
> > Documentation/devicetree/bindings/video/display-timing.txt.
> > 
> > 
> > 
> > 
> > Please note that most of the display entities on devices I own are just
> > dumb panels with no control bus, and are thus not the best candidates to
> > design a framework that needs to take complex panels' needs into account.
> > This is why I hope to see you using the CDF with your display device and
> > tell me what needs to be modified/improved/redesigned.
> > 
> > This patch set is split as follows:
> > 
> > - The first patch fixes a Kconfig namespace issue with the OMAP DSS
> > panels. It> 
> >   could be applied already independently of this series.
> > 
> > - Patches 02/19 to 07/19 add the CDF core, including the notification
> > system> 
> >   and the graph and OF helpers.
> > 
> > - Patch 08/19 adds a MIPI DBI bus. This isn't part of CDF strictly
> > speaking,> 
> >   but is needed for the DBI panel drivers.
> > 
> > - Patches 09/19 to 13/19 add panel drivers, a VGA DAC driver and a VGA
> > 
> >   connector driver.
> > 
> > - Patches 14/19 to 18/19 add CDF-compliant reference board code and DT for
> > the> 
> >   Renesas Marzen and Lager boards.
> > 
> > - Patch 19/19 port the Renesas R-Car Display Unit driver to CDF.
> > 
> > The patches are available in my git tree at
> > 
> >     git://linuxtv.org/pinchartl/fbdev.git cdf/v3
> >     http://git.linuxtv.org/pinchartl/fbdev.git/shortlog/refs/heads/cdf/v3
> > 
> > For convenience I've included modifications to the Renesas R-Car Display
> > Unit driver to use the CDF. You can read the code to see how the driver
> > uses CDF to interface panels. Please note that the rcar-du-drm
> > implementation is still work in progress, its set_stream operation
> > implementation doesn't enable and disable the video stream yet as it
> > should.
> > 
> > As already mentioned in v2, I will appreciate all reviews, comments,
> > criticisms, ideas, remarks, ... If you can find a clever way to solve the
> > cyclic references issue described above I'll buy you a beer at the next
> > conference we will both attend. If you think the proposed solution is too
> > complex, or too simple, I'm all ears, but I'll have more arguments this
> > time than I had with v2 :-)
> > 
> > Laurent Pinchart (19):
> >   OMAPDSS: panels: Rename Kconfig options to OMAP2_DISPLAY_*
> >   video: Add Common Display Framework core
> >   video: display: Add video and stream control operations
> >   video: display: Add display entity notifier
> >   video: display: Graph helpers
> >   video: display: OF support
> >   video: display: Add pixel coding definitions
> >   video: display: Add MIPI DBI bus support
> >   video: panel: Add DPI panel support
> >   video: panel: Add R61505 panel support
> >   video: panel: Add R61517 panel support
> >   video: display: Add VGA Digital to Analog Converter support
> >   video: display: Add VGA connector support
> >   ARM: shmobile: r8a7790: Add DU clocks for DT
> >   ARM: shmobile: r8a7790: Add DU device node to device tree
> >   ARM: shmobile: marzen: Port DU platform data to CDF
> >   ARM: shmobile: lager: Port DU platform data to CDF
> >   ARM: shmobile: lager-reference: Add display device nodes to device
> >   
> >     tree
> >   
> >   drm/rcar-du: Port to the Common Display Framework
> >  
> >  arch/arm/boot/dts/r8a7790-lager-reference.dts |  92 ++++
> >  arch/arm/boot/dts/r8a7790.dtsi                |  33 ++
> >  arch/arm/mach-shmobile/board-lager.c          |  76 ++-
> >  arch/arm/mach-shmobile/board-marzen.c         |  77 ++-
> >  arch/arm/mach-shmobile/clock-r8a7790.c        |   5 +
> >  drivers/gpu/drm/rcar-du/Kconfig               |   3 +-
> >  drivers/gpu/drm/rcar-du/Makefile              |   7 +-
> >  drivers/gpu/drm/rcar-du/rcar_du_connector.c   | 164 ++++++
> >  drivers/gpu/drm/rcar-du/rcar_du_connector.h   |  36 ++
> >  drivers/gpu/drm/rcar-du/rcar_du_crtc.h        |   2 +-
> >  drivers/gpu/drm/rcar-du/rcar_du_drv.c         | 279 ++++++++--
> >  drivers/gpu/drm/rcar-du/rcar_du_drv.h         |  28 +-
> >  drivers/gpu/drm/rcar-du/rcar_du_encoder.c     |  87 ++-
> >  drivers/gpu/drm/rcar-du/rcar_du_encoder.h     |  22 +-
> >  drivers/gpu/drm/rcar-du/rcar_du_kms.c         | 116 +++-
> >  drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c     | 131 -----
> >  drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h     |  25 -
> >  drivers/gpu/drm/rcar-du/rcar_du_vgacon.c      |  96 ----
> >  drivers/gpu/drm/rcar-du/rcar_du_vgacon.h      |  23 -
> >  drivers/video/Kconfig                         |   1 +
> >  drivers/video/Makefile                        |   1 +
> >  drivers/video/display/Kconfig                 |  62 +++
> >  drivers/video/display/Makefile                |   9 +
> >  drivers/video/display/con-vga.c               | 148 +++++
> >  drivers/video/display/display-core.c          | 759 +++++++++++++++++++++
> >  drivers/video/display/display-notifier.c      | 542 ++++++++++++++++++
> >  drivers/video/display/mipi-dbi-bus.c          | 234 ++++++++
> >  drivers/video/display/panel-dpi.c             | 207 +++++++
> >  drivers/video/display/panel-r61505.c          | 567 +++++++++++++++++++
> >  drivers/video/display/panel-r61517.c          | 460 ++++++++++++++++
> >  drivers/video/display/vga-dac.c               | 152 ++++++
> >  drivers/video/omap2/displays-new/Kconfig      |  24 +-
> >  drivers/video/omap2/displays-new/Makefile     |  24 +-
> >  include/linux/platform_data/rcar-du.h         |  55 +-
> >  include/video/display.h                       | 398 ++++++++++++++
> >  include/video/mipi-dbi-bus.h                  | 125 +++++
> >  include/video/panel-dpi.h                     |  24 +
> >  include/video/panel-r61505.h                  |  27 +
> >  include/video/panel-r61517.h                  |  28 +
> >  39 files changed, 4615 insertions(+), 534 deletions(-)
> >  create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_connector.c
> >  create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_connector.h
> >  delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
> >  delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_lvdscon.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/video/display/Kconfig
> >  create mode 100644 drivers/video/display/Makefile
> >  create mode 100644 drivers/video/display/con-vga.c
> >  create mode 100644 drivers/video/display/display-core.c
> >  create mode 100644 drivers/video/display/display-notifier.c
> >  create mode 100644 drivers/video/display/mipi-dbi-bus.c
> >  create mode 100644 drivers/video/display/panel-dpi.c
> >  create mode 100644 drivers/video/display/panel-r61505.c
> >  create mode 100644 drivers/video/display/panel-r61517.c
> >  create mode 100644 drivers/video/display/vga-dac.c
> >  create mode 100644 include/video/display.h
> >  create mode 100644 include/video/mipi-dbi-bus.h
> >  create mode 100644 include/video/panel-dpi.h
> >  create mode 100644 include/video/panel-r61505.h
> >  create mode 100644 include/video/panel-r61517.h

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
  2013-08-20 15:24   ` Laurent Pinchart
@ 2013-08-20 18:40     ` Rob Clark
  2013-08-21  7:09       ` Sascha Hauer
  0 siblings, 1 reply; 83+ messages in thread
From: Rob Clark @ 2013-08-20 18:40 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: Linux Fbdev development list, Benjamin Gaignard, dri-devel,
	Jesse Barnes, Sebastien Guiriec, Laurent Pinchart, Tom Gall,
	Ragesh Radhakrishnan, Tomi Valkeinen, linux-media,
	Stephen Warren, Mark Zhang, Stéphane Marchesin,
	Alexandre Courbot, Thomas Petazzoni, Sunil Joshi, Kyungmin Park,
	Maxime Ripard

On Tue, Aug 20, 2013 at 11:24 AM, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> Hi Rob,
>
> On Tuesday 13 August 2013 20:43:50 Rob Clark wrote:
>> On Fri, Aug 9, 2013 at 1:14 PM, Laurent Pinchart wrote:
>> > Hi everybody,
>> >
>> > Here's the third RFC of the Common Display Framework.
>> >
>> > I won't repeat all the background information from the versions one and
>> > two here, you can read it at http://lwn.net/Articles/512363/ and
>> > http://lwn.net/Articles/526965/.
>> >
>> > This RFC isn't final. Given the high interest in CDF and the urgent tasks
>> > that kept delaying the next version of the patch set, I've decided to
>> > release v3 before completing all parts of the implementation. Known
>> > missing items are
>> >
>> > - documentation: kerneldoc and this cover letter should provide basic
>> >   information, more extensive documentation will likely make it to v4.
>> >
>> > - pipeline configuration and control: generic code to configure and
>> >   control display pipelines (in a nutshell, translating high-level mode
>> >   setting and DPMS calls to low-level entity operations) is missing. Video
>> >   and stream control operations have been carried over from v2, but will
>> >   need to be revised for v4.
>> >
>> > - DSI support: I still have no DSI hardware I can easily test the code on.
>>
>> tbh, I kinda think that DSI and bridge chips are the things we should focus
>> on first.. that seems what is most important for current and new hardware.
>> Back-filling to handle older/simpler panels can be done later.
>
> That sounds reasonable (although I still believe DSI is only part of the
> issue), but I'll need help with that, as the Renesas platforms I work on don't
> have a DSI bus.
>
>> > Special thanks go to
>> >
>> > - Renesas for inviting me to LinuxCon Japan 2013 where I had the
>> >   opportunity to validate the CDF v3 concepts with Alexandre Courbot
>> >   (NVidia) and Tomasz Figa (Samsung).
>> >
>> > - Tomi Valkeinen (TI) for taking the time to deeply brainstorm v3 with me.
>> >
>> > - Linaro for inviting me to Linaro Connect Europe 2013, the discussions we
>> >   had  there greatly helped moving CDF forward.
>> >
>> > - And of course all the developers who showed interest in CDF and spent
>> >   time sharing ideas, reviewing patches and testing code.
>> >
>> > I have to confess I was a bit lost and discouraged after all the CDF-
>> > related meetings during which we have discussed how to move from v2 to v3.
>> > With every meeting I was hoping to run the implementation through use
>> > cases of various interesting parties and narrow down the scope of the huge
>> > fuzzy beast that CDF was. With every meeting the scope actually broadened,
>> > with no clear path at sight anywhere.
>> >
>> > Earlier this year I was about to drop one of the requirements on which I
>> > had based CDF v2: sharing drivers between DRM/KMS and V4L2. With only two
>> > HDMI transmitters as use cases for that feature (with only out-of-tree
>> > drivers so far), I just thought the involved completely wasn't worth it
>> > and that I should implement CDF v3 as a DRM/KMS-only helper framework.
>> > However, a seemingly unrelated discussion with Xilinx developers showed
>> > me that hybrid SoC-FPGA platforms such as the Xilinx Zynq 7000 have a
>> > larger library of IP cores that can be used in camera capture pipelines
>> > and in display pipelines. The two use cases suddenly became tens or even
>> > hundreds of use cases that I couldn't ignore anymore.
>>
>> Hmm, I'm still not really convinced ;-)
>>
>> Or maybe, put another way, I still think we should still optimize for the
>> common case. I mean I'm sure you *can* design hw that has an LVDS->DP bridge
>> in the capture path, and if you had something like an FPGA where that was
>> cheap to do maybe you even would (for fun). But if in the real world, there
>> are only one or two cases of actual hw using the same bridge in a capture
>> pipeline which is normally used in display pipelines, then duplicating some
>> small bit of code for that abnormal case if it makes things easier for the
>> common case, seems like a reasonable trade-off to me.
>
> That was my opinion as well until I started working on a Xilinx platform.
> There's dozens of IP cores there that are used in both capture and display
> pipelines.

or maybe just some helper lib's to handling the register level programming?

Anyways, I guess you can call it a "worse is better" thing, but if you
can get 90% of the desired effect for 10% of the work, take the
simpler solution.  I don't think we should make things more layered or
more difficult for one exceptional case.


> Furthermore, FPGA display pipelines being made of individual IP cores, we need
> a way to write one driver per IP core and make them all interact. The recently
> proposed drm_bridge is one possible solution to this issue (and to a different
> but similar issue that trigerred the development of drm_bridge), but it's in
> my opinion not generic enough. We're facing several problems that are related,
> it would really be a shame not to solve them with a good enough framework.

well, I've been working on DSI panel support in msm drm, and also been
looking at the patches to add DSI support in i915.  And the panel
interface ends up looking basically like the drm_bridge interface.
Perhaps the only thing not generic there is the name.

>> I mean, take a DSI panel driver, for example.. anything but a trivial panel
>> driver, you are going to want to expose some custom properties on the
>> connector for controlling non-standard features. So you end up with both
>> cdf_foo for the common part, and drm_foo for gluing in the properties. And
>> now these two parts which otherwise would be one, end up having to stay in
>> sync merged through different trees, etc. It seems a lot like making my life
>> more difficult for a fairly hypothetical gain ;-)
>
> The DSI panel driver should not be split into two parts. It should implement a
> CDF entity, any glue needed for DRM will not be part of the panel driver.

right, but that glue ends up needing to be *somewhere*, which makes it
the 2nd part.

>> Or, take an hdmi or DP bridge. To use any of the common
>> infrastructure/helpers in drm, you end up implementing a generic interface,
>> where both the producer and consumer is inside drm. Which just seems a bit
>> pointless and extra hoops to jump through. Especially when we discover that
>> we need to extend/enhance the common interface outside of drm to make it
>> work. (I'm thinking of display_entity_control_ops::get_modes() here, but I'm
>> sure there are more examples.) And I think we'll run into similar issues
>> with display_entity_control_ops::set_state(), since the on<->off sequencing
>> can get hairy when the upstream/downstream entity is fed a clk by the
>> downstream/upstream entity. And similarly, I think we'll go through a few
>> revisions of DSI panel/bus params before we have everything that everyone
>> needs.
>
> I don't see where needing multiple revisions of a patch set would be bad :-)

I mean over multiple kernel revisions, as people start adding support
for new hw and run into limitations of the "framework".

We've already figured out that just having enable() and disable() is
not sufficient for displayport link training.  I'm not sure what else
we'll discover.

>> (Don't get me wrong.. if we were starting from scratch, I'd tend to think
>> that stuff downstream of the crtc should share common framework w/ v4l.. but
>> we are pretty far from starting from scratch, and how to get from where we
>> are today to future is just as important as the end result.)
>
> Then let's discuss how to get there. We have issues we need to solve, and we
> need a new framework for that. There's no way to share panel drivers today, no
> way to design DT bindings for them, no way to avoid duplicating dozens of IP
> core drivers in FPGAs, no way to support chained encoders (as shown by the
> drm_bridge proposal). All those problems must be solved now, not in a couple
> of years. The window of opportunity is here, and I don't want to waste it.

I'm not saying not to solve (most of these) problems.. I don't think
chaining multiple drm_bridge's is impossible, I can think of at least
two ways to implement it.  But I think we should solve that as someone
is adding support for hw that uses this.  This (a) lets us break
things up into smaller more incremental changes (drm_bridge is
*considerably* smaller than the current CDF patchset), and (b) avoids
us solving the wrong problems.

btw, I think DT bindings is orthogonal to this discussion.

Anyways, if I were starting from scratch, drm_mode_object,
drm_display_mode, and drm-properties would all be part of the common
layer.  All the edid and displayport helpers and maybe some other bits
would be pushed down to the common layer, so that we could actually
use these encoders/bridges/panels/whatever.  But maybe start looking
at the size of some of the desktop drivers before you start thinking
that is a good idea.

BR,
-R

>> > CDF v3 is thus userspace API agnostic. It isn't tied to DRM/KMS or V4L2
>> > and can be used by any kernel subsystem, potentially including FBDEV
>> > (although I won't personally wrote FBDEV support code, as I've already
>> > advocated for FBDEV to be deprecated).
>> >
>> > The code you are about to read is based on the concept of display entities
>> > introduced in v2. Diagrams related to the explanations below are available
>> > at http://ideasonboard.org/media/cdf/20130709-lce-cdf.pdf.
>> >
>> >
>> > Display Entities
>> > ----------------
>> >
>> > A display entity abstracts any hardware block that sources, processes or
>> > sinks display-related video streams. It offers an abstract API,
>> > implemented by display entity drivers, that is used by master drivers
>> > (such as the main display driver) to query, configure and control display
>> > pipelines.
>> >
>> > Display entities are connected to at least one video data bus, and
>> > optionally to a control bus. The video data busses carry display-related
>> > video data out of sources (such as a CRTC in a display controller) to
>> > sinks (such as a panel or a monitor), optionally going through
>> > transmitters, encoders, decoders, bridges or other similar devices. A
>> > CRTC or a panel will usually be connected to a single data bus, while an
>> > encoder or a transmitter will be connected to two data busses.
>> >
>> > The simple linear display pipelines we find in most embedded platforms at
>> > the moment are expected to grow more complex with time. CDF needs to
>> > accomodate those needs from the start to be, if not future-proof, at
>> > least present-proof at the time it will get merged in to mainline. For
>> > this reason display entities have data ports through which video streams
>> > flow in or out, with link objects representing the connections between
>> > those ports. A typical entity in a linear display pipeline will have one
>> > (for video source and video sink entities such as CRTCs or panels) or two
>> > ports (for video processing entities such as encoders), but more ports
>> > are allowed, and entities can be linked in complex non-linear pipelines.
>> >
>> > Readers might think that this model if extremely similar to the media
>> > controller graph model. They would be right, and given my background this
>> > is most probably not a coincidence. The CDF v3 implementation uses the
>> > in-kernel media controller framework to model the graph of display
>> > entities, with the display entity data structure inheriting from the
>> > media entity structure. The display pipeline graph topology will be
>> > automatically exposed to userspace through the media controller API as an
>> > added bonus. However, ussage of the media controller userspace API in
>> > applications is *not* mandatory, and the current CDF implementation
>> > doesn't use the media controller link setup userspace API to configure
>> > the display pipelines.
>> >
>> > While some display entities don't require any configuration (DPI panels
>> > are a good example), many of them are connected to a control bus
>> > accessible to the CPU. Control requests can be sent on a dedicated
>> > control bus (such as I2C or SPI) or multiplexed on a mixed control and
>> > data bus (such as DBI or DSI). To support both options the CDF display
>> > entity model separates the control and data busses in different APIs.
>> >
>> > Display entities are abstract object that must be implemented by a real
>> > device. The device sits on its control bus and is registered with the
>> > Linux
>> > device core and matched with his driver using the control bus specific
>> > API.
>> > The CDF doesn't create a display entity class or bus, display entity
>> > drivers thus standard Linux kernel drivers using existing busses. A DBI
>> > bus is added as part of this patch set, but strictly speaking this isn't
>> > part of CDF.
>> >
>> > When a display entity driver probes a device it must create an instance of
>> > the display_entity structure, initialize it and add it to the CDF core
>> > entities pool. The display entity exposes abstract operations through
>> > function pointers, and the entity driver must implement those operations.
>> > Those operations can act on either the whole entity or on a given port,
>> > depending on the operation. They are divided in two groups, control
>> > operations and video operations.
>> >
>> >
>> > Control Operations
>> > ------------------
>> >
>> > Control operations are called by upper-level drivers, usually in response
>> > to a request originating from userspace. They query or control the
>> > display entity state and operation. Currently defined control operations
>> > are
>> >
>> > - get_size(), to retrieve the entity physical size (applicable to panels
>> > only) - get_modes(), to retrieve the video modes supported at an entity
>> > port - get_params(), to retrieve the data bus parameters at an entity
>> > port
>> >
>> > - set_state(), to control the state of the entity (off, standby or on)
>> > - update(), to trigger a display update (for entities that implement
>> > manual
>> >
>> >   update, such as manual-update panels that store frames in their internal
>> >   frame buffer)
>> >
>> > The last two operations have been carried from v2 and will be reworked.
>> >
>> >
>> > Pipeline Control
>> > ----------------
>> >
>> > The figure on page 4 shows the control model for a linear pipeline. This
>> > differs significantly from CDF v2 where calls where forwarded from entity
>> > to entity using a Russian dolls model. v3 removes the need of neighbour
>> > awareness from entity drivers, simplifying the entity drivers. The
>> > complexity of pipeline configuration is moved to a central location
>> > called a pipeline controller instead of being spread out to all drivers.
>> >
>> > Pipeline controllers provide library functions that display drivers can
>> > use to control a pipeline. Several controllers can be implemented to
>> > accomodate the needs of various pipeline topologies and complexities, and
>> > display drivers can even implement their own pipeline control algorithm
>> > if needed. I'm working on a linear pipeline controller for the next
>> > version of the patch set.
>> >
>> > If pipeline controllers are responsible for propagating a pipeline
>> > configuration on all entity ports in the pipeline, entity drivers are
>> > responsible for propagating the configuration inside entities, from sink
>> > (input) to source (output) ports as illustrated on page 5. The rationale
>> > behind this is that knowledge of the entity internals is located in the
>> > entity driver, while knowledge of the pipeline belongs to the pipeline
>> > controller. The controller will thus configure the pipeline by performing
>> > the following steps:
>> >
>> > - applying a configuration on sink ports of an entity
>> > - read the configuration that has been propagated by the entity driver on
>> > its>
>> >   source ports
>> >
>> > - optionally, modify the source port configuration (to configure custom
>> > timings,>
>> >   scaling or other parameters, if supported by the entity)
>> >
>> > - propagate the source port configuration to the sink ports of the next
>> > entities>
>> >   in the pipeline and start over
>> >
>> > Beside modifying the active configuration, the entities API will allow
>> > trying configurations without applying them to the hardware. As
>> > configuration of a port possibly depend on the configurations of the
>> > other ports, trying a configuration must be done at the entity level
>> > instead of the port level. The implementation will be based on the
>> > concept of configuration store objects that will store the configuration
>> > of all ports for a given entity. Each entity will have a single active
>> > configuration store, and test configuration stores will be created
>> > dynamically to try a configuration on an entity. The get and set
>> > operations implemented by the entity will receive a configuration store
>> > pointer, and active and test code paths in entity drivers will be
>> > identical, except for applying the configuration to the hardware for the
>> > active code path.
>> >
>> >
>> > Video Operations
>> > ----------------
>> >
>> > Video operations control the video stream state on entity ports. The only
>> > currently defined video operation is
>> >
>> > - set_stream(), to start (in continuous or single-shot mode) the video
>> > stream>
>> >   on an entity port
>> >
>> > The call model for video operations differ from the control operations
>> > model described above. The set_stream() operation is called directly by
>> > downstream entities on upstream entities (from a video data bus point of
>> > view). Terminating entities in a pipeline (such as panels) will usually
>> > call the set_stream() operation in their set_state() handler, and
>> > intermediate entities will forward the set_stream() call upstream.
>> >
>> >
>> > Integration
>> > -----------
>> >
>> > The figure on page 8 describes how a panel driver, implemented using CDF
>> > as a display entity, interacts with the other components in the system.
>> > The use case is a simple pipeline made of a display controller and a
>> > panel.
>> >
>> > The display controller driver receives control request from userspace
>> > through DRM (or FBDEV) API calls. It processes the request and calls the
>> > panel driver through the CDF control operations API. The panel driver
>> > will then issue requests on its control bus (several possible control
>> > busses are shown on the figure, panel drivers typically use one of them
>> > only) and call video operations of the display controller on its left
>> > side to control the video stream.
>> >
>> >
>> > Registration and Notification
>> > -----------------------------
>> >
>> > Due to possibly complex dependencies between entities we can't guarantee
>> > that all entities part of the display pipeline will have been
>> > successfully probed when the master display controller driver is probed.
>> > For instance a panel can be a child of the DBI or DSI bus controlled by
>> > the display device, or use a clock provided by that device. We can't
>> > defer the display device probe until the panel is probed and also defer
>> > the panel device probe until the display device is probed. For this
>> > reason we need a notification system that allows entities to register
>> > themselves with the CDF core, and display controller drivers to get
>> > notified when entities they need are available.
>> >
>> > The notification system has been completely redesigned in v3. This version
>> > is based on the V4L2 asynchronous probing notification code, with large
>> > parts of the code shamelessly copied. This is an interim solution to let
>> > me play with the notification code as needed by CDF. I'm not a fan of
>> > code duplication, and will work on merging the CDF and V4L2
>> > implementations in a later stage when CDF will reach a mature enough
>> > state.
>> >
>> > CDF manages a pool of entities and a list of notifiers. Notifiers are
>> > registered by master display drivers with an array of entities match
>> > descriptors. When an entity is added to the CDF entities pool, all
>> > notifiers are searched for a match. If a match is found, the
>> > corresponding notifier is called to notify the master display driver.
>> >
>> > The two currently supported match methods are platform match, which uses
>> > device names, and DT match, which uses DT node pointers. More match method
>> > might be added later if needed. Two helper functions exist to build a
>> > notifier from a list of platform device names (in the non-DT case) or a
>> > DT
>> > representation of the display pipeline topology.
>> >
>> > Once all required entities have been successfully found, the master
>> > display
>> > driver is responsible for creating media controller links between all
>> > entities in the pipeline. Two helper functions are also available to
>> > automate that process, one for the non-DT case and one for the DT case.
>> > Once again some DT-related code has been copied from the V4L2 DT code, I
>> > will work on merging both in a future version.
>> >
>> > Note that notification brings a different issue after registration, as
>> > display controller and display entity drivers would take a reference to
>> > each other. Those circular references would make driver unloading
>> > impossible. One possible solution to this problem would be to simulate an
>> > unplug event for the display entity, to force the display driver to
>> > release the dislay entities it uses. We would need a userspace API for
>> > that though. Better solutions would of course be welcome.
>> >
>> >
>> > Device Tree Bindings
>> > --------------------
>> >
>> > CDF entities device tree bindings are not documented yet. They describe
>> > both the graph topology and entity-specific information. The graph
>> > description uses the V4L2 DT bindings (which are actually not
>> > V4L2-specific) specified at
>> > Documentation/devicetree/bindings/media/video-interfaces.txt.
>> > Entity-specific information will be described in individual DT bindings
>> > documentation. The DPI panel driver uses the display timing bindings
>> > documented in
>> > Documentation/devicetree/bindings/video/display-timing.txt.
>> >
>> >
>> >
>> >
>> > Please note that most of the display entities on devices I own are just
>> > dumb panels with no control bus, and are thus not the best candidates to
>> > design a framework that needs to take complex panels' needs into account.
>> > This is why I hope to see you using the CDF with your display device and
>> > tell me what needs to be modified/improved/redesigned.
>> >
>> > This patch set is split as follows:
>> >
>> > - The first patch fixes a Kconfig namespace issue with the OMAP DSS
>> > panels. It>
>> >   could be applied already independently of this series.
>> >
>> > - Patches 02/19 to 07/19 add the CDF core, including the notification
>> > system>
>> >   and the graph and OF helpers.
>> >
>> > - Patch 08/19 adds a MIPI DBI bus. This isn't part of CDF strictly
>> > speaking,>
>> >   but is needed for the DBI panel drivers.
>> >
>> > - Patches 09/19 to 13/19 add panel drivers, a VGA DAC driver and a VGA
>> >
>> >   connector driver.
>> >
>> > - Patches 14/19 to 18/19 add CDF-compliant reference board code and DT for
>> > the>
>> >   Renesas Marzen and Lager boards.
>> >
>> > - Patch 19/19 port the Renesas R-Car Display Unit driver to CDF.
>> >
>> > The patches are available in my git tree at
>> >
>> >     git://linuxtv.org/pinchartl/fbdev.git cdf/v3
>> >     http://git.linuxtv.org/pinchartl/fbdev.git/shortlog/refs/heads/cdf/v3
>> >
>> > For convenience I've included modifications to the Renesas R-Car Display
>> > Unit driver to use the CDF. You can read the code to see how the driver
>> > uses CDF to interface panels. Please note that the rcar-du-drm
>> > implementation is still work in progress, its set_stream operation
>> > implementation doesn't enable and disable the video stream yet as it
>> > should.
>> >
>> > As already mentioned in v2, I will appreciate all reviews, comments,
>> > criticisms, ideas, remarks, ... If you can find a clever way to solve the
>> > cyclic references issue described above I'll buy you a beer at the next
>> > conference we will both attend. If you think the proposed solution is too
>> > complex, or too simple, I'm all ears, but I'll have more arguments this
>> > time than I had with v2 :-)
>> >
>> > Laurent Pinchart (19):
>> >   OMAPDSS: panels: Rename Kconfig options to OMAP2_DISPLAY_*
>> >   video: Add Common Display Framework core
>> >   video: display: Add video and stream control operations
>> >   video: display: Add display entity notifier
>> >   video: display: Graph helpers
>> >   video: display: OF support
>> >   video: display: Add pixel coding definitions
>> >   video: display: Add MIPI DBI bus support
>> >   video: panel: Add DPI panel support
>> >   video: panel: Add R61505 panel support
>> >   video: panel: Add R61517 panel support
>> >   video: display: Add VGA Digital to Analog Converter support
>> >   video: display: Add VGA connector support
>> >   ARM: shmobile: r8a7790: Add DU clocks for DT
>> >   ARM: shmobile: r8a7790: Add DU device node to device tree
>> >   ARM: shmobile: marzen: Port DU platform data to CDF
>> >   ARM: shmobile: lager: Port DU platform data to CDF
>> >   ARM: shmobile: lager-reference: Add display device nodes to device
>> >
>> >     tree
>> >
>> >   drm/rcar-du: Port to the Common Display Framework
>> >
>> >  arch/arm/boot/dts/r8a7790-lager-reference.dts |  92 ++++
>> >  arch/arm/boot/dts/r8a7790.dtsi                |  33 ++
>> >  arch/arm/mach-shmobile/board-lager.c          |  76 ++-
>> >  arch/arm/mach-shmobile/board-marzen.c         |  77 ++-
>> >  arch/arm/mach-shmobile/clock-r8a7790.c        |   5 +
>> >  drivers/gpu/drm/rcar-du/Kconfig               |   3 +-
>> >  drivers/gpu/drm/rcar-du/Makefile              |   7 +-
>> >  drivers/gpu/drm/rcar-du/rcar_du_connector.c   | 164 ++++++
>> >  drivers/gpu/drm/rcar-du/rcar_du_connector.h   |  36 ++
>> >  drivers/gpu/drm/rcar-du/rcar_du_crtc.h        |   2 +-
>> >  drivers/gpu/drm/rcar-du/rcar_du_drv.c         | 279 ++++++++--
>> >  drivers/gpu/drm/rcar-du/rcar_du_drv.h         |  28 +-
>> >  drivers/gpu/drm/rcar-du/rcar_du_encoder.c     |  87 ++-
>> >  drivers/gpu/drm/rcar-du/rcar_du_encoder.h     |  22 +-
>> >  drivers/gpu/drm/rcar-du/rcar_du_kms.c         | 116 +++-
>> >  drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c     | 131 -----
>> >  drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h     |  25 -
>> >  drivers/gpu/drm/rcar-du/rcar_du_vgacon.c      |  96 ----
>> >  drivers/gpu/drm/rcar-du/rcar_du_vgacon.h      |  23 -
>> >  drivers/video/Kconfig                         |   1 +
>> >  drivers/video/Makefile                        |   1 +
>> >  drivers/video/display/Kconfig                 |  62 +++
>> >  drivers/video/display/Makefile                |   9 +
>> >  drivers/video/display/con-vga.c               | 148 +++++
>> >  drivers/video/display/display-core.c          | 759 +++++++++++++++++++++
>> >  drivers/video/display/display-notifier.c      | 542 ++++++++++++++++++
>> >  drivers/video/display/mipi-dbi-bus.c          | 234 ++++++++
>> >  drivers/video/display/panel-dpi.c             | 207 +++++++
>> >  drivers/video/display/panel-r61505.c          | 567 +++++++++++++++++++
>> >  drivers/video/display/panel-r61517.c          | 460 ++++++++++++++++
>> >  drivers/video/display/vga-dac.c               | 152 ++++++
>> >  drivers/video/omap2/displays-new/Kconfig      |  24 +-
>> >  drivers/video/omap2/displays-new/Makefile     |  24 +-
>> >  include/linux/platform_data/rcar-du.h         |  55 +-
>> >  include/video/display.h                       | 398 ++++++++++++++
>> >  include/video/mipi-dbi-bus.h                  | 125 +++++
>> >  include/video/panel-dpi.h                     |  24 +
>> >  include/video/panel-r61505.h                  |  27 +
>> >  include/video/panel-r61517.h                  |  28 +
>> >  39 files changed, 4615 insertions(+), 534 deletions(-)
>> >  create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_connector.c
>> >  create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_connector.h
>> >  delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
>> >  delete mode 100644 drivers/gpu/drm/rcar-du/rcar_du_lvdscon.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/video/display/Kconfig
>> >  create mode 100644 drivers/video/display/Makefile
>> >  create mode 100644 drivers/video/display/con-vga.c
>> >  create mode 100644 drivers/video/display/display-core.c
>> >  create mode 100644 drivers/video/display/display-notifier.c
>> >  create mode 100644 drivers/video/display/mipi-dbi-bus.c
>> >  create mode 100644 drivers/video/display/panel-dpi.c
>> >  create mode 100644 drivers/video/display/panel-r61505.c
>> >  create mode 100644 drivers/video/display/panel-r61517.c
>> >  create mode 100644 drivers/video/display/vga-dac.c
>> >  create mode 100644 include/video/display.h
>> >  create mode 100644 include/video/mipi-dbi-bus.h
>> >  create mode 100644 include/video/panel-dpi.h
>> >  create mode 100644 include/video/panel-r61505.h
>> >  create mode 100644 include/video/panel-r61517.h
>
> --
> Regards,
>
> Laurent Pinchart
>

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 06/19] video: display: OF support
  2013-08-13 14:37   ` Philipp Zabel
@ 2013-08-21  1:02     ` Laurent Pinchart
  2013-08-21  9:10       ` Philipp Zabel
  0 siblings, 1 reply; 83+ messages in thread
From: Laurent Pinchart @ 2013-08-21  1:02 UTC (permalink / raw)
  To: Philipp Zabel, Stephen Warren
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Laurent Pinchart, Tom Gall, Kyungmin Park, Tomi Valkeinen,
	linux-media, Mark Zhang, Stéphane Marchesin,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

Hi Philipp,

On Tuesday 13 August 2013 16:37:07 Philipp Zabel wrote:
> Hi Laurent,
> 
> thanks for this update. I'm very happy about the move to the display entity
> model, given that the i.MX6 IPU has both drm/display and v4l2/capture ports
> in a single device - this will allow to use a unified device tree binding
> scheme.

Thanks for the support :-)

> I'm still trying to see how this all fits together, so far I have only one
> comment, below.
> 
> Am Freitag, den 09.08.2013, 19:14 +0200 schrieb Laurent Pinchart:
> [...]
> 
> > +static int display_of_parse_dt(struct display_entity_notifier *notifier,
> > +			       struct list_head *entities,
> > +			       struct device_node *node)
> > +{
> > +	struct display_entity_of *entity;
> > +	struct device_node *remote;
> > +	struct device_node *ep = NULL;
> > +	struct device_node *next;
> > +	unsigned int num_entities = 0;
> > +	int ret = 0;
> > +
> > +	/* Walk the device tree and build a list of nodes. */
> > +	dev_dbg(notifier->dev, "parsing node %s\n", node->full_name);
> > +
> > +	while (1) {
> > +		next = display_of_get_next_endpoint(node, ep);
> > +		if (next == NULL)
> > +			break;
> > +
> > +		of_node_put(ep);
> > +		ep = next;
> > +
> > +		dev_dbg(notifier->dev, "handling endpoint %s\n", ep->full_name);
> > +
> > +		remote = display_of_get_remote_port_parent(ep);
> > +		if (remote == NULL)
> > +			continue;
> > +
> > +		/* Skip entities that we have already processed. */
> > +		if (display_of_find_entity(entities, remote) || remote == node) {
> > +			dev_dbg(notifier->dev,
> > +				"entity %s already in list, skipping\n",
> > +				remote->full_name);
> > +			continue;
> > +		}
> 
> device tree nodes with status = "disabled" should be skipped here:
> 
>                 if (!of_device_is_available(remote)) {
>                         dev_dbg(notifier->dev,
>                                 "entity %s is disabled, skipping\n",
>                                 remote->full_name);
>                         continue;
>                 }
> 
> Otherwise the completion notification will never be delivered if there
> are any disabled entities in the graph.

That's a good point, but if a device is disabled, why would it be in the DT 
graph in the first place ? Do you have a use case for this ?

> > +		entity = kzalloc(sizeof(*entity), GFP_KERNEL);
> > +		if (entity == NULL) {
> > +			of_node_put(remote);
> > +			ret = -ENOMEM;
> > +			break;
> > +		}
> > +
> > +		dev_dbg(notifier->dev, "adding remote entity %s to list\n",
> > +			remote->full_name);
> > +
> > +		entity->node = remote;
> > +		list_add_tail(&entity->list, entities);
> > +		num_entities++;
> > +	}
> > +
> > +	of_node_put(ep);
> > +
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	return num_entities;
> > +}
> 
> [...]

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
  2013-08-20 18:40     ` Rob Clark
@ 2013-08-21  7:09       ` Sascha Hauer
  2013-08-21 12:22         ` Rob Clark
  0 siblings, 1 reply; 83+ messages in thread
From: Sascha Hauer @ 2013-08-21  7:09 UTC (permalink / raw)
  To: Rob Clark
  Cc: Linux Fbdev development list, Benjamin Gaignard, dri-devel,
	Jesse Barnes, Laurent Pinchart, Sebastien Guiriec,
	Laurent Pinchart, Tom Gall, Ragesh Radhakrishnan, Tomi Valkeinen,
	linux-media, Stephen Warren, Mark Zhang, Stéphane Marchesin,
	Alexandre Courbot, Thomas Petazzoni, Sunil Joshi, Kyungmin Park

On Tue, Aug 20, 2013 at 02:40:55PM -0400, Rob Clark wrote:
> On Tue, Aug 20, 2013 at 11:24 AM, Laurent Pinchart
> <laurent.pinchart@ideasonboard.com> wrote:
> > Hi Rob,
> >
> >> Or maybe, put another way, I still think we should still optimize for the
> >> common case. I mean I'm sure you *can* design hw that has an LVDS->DP bridge
> >> in the capture path, and if you had something like an FPGA where that was
> >> cheap to do maybe you even would (for fun). But if in the real world, there
> >> are only one or two cases of actual hw using the same bridge in a capture
> >> pipeline which is normally used in display pipelines, then duplicating some
> >> small bit of code for that abnormal case if it makes things easier for the
> >> common case, seems like a reasonable trade-off to me.
> >
> > That was my opinion as well until I started working on a Xilinx platform.
> > There's dozens of IP cores there that are used in both capture and display
> > pipelines.
> 
> or maybe just some helper lib's to handling the register level programming?
> 
> Anyways, I guess you can call it a "worse is better" thing, but if you
> can get 90% of the desired effect for 10% of the work, take the
> simpler solution.  I don't think we should make things more layered or
> more difficult for one exceptional case.
> 
> 
> > Furthermore, FPGA display pipelines being made of individual IP cores, we need
> > a way to write one driver per IP core and make them all interact. The recently
> > proposed drm_bridge is one possible solution to this issue (and to a different
> > but similar issue that trigerred the development of drm_bridge), but it's in
> > my opinion not generic enough. We're facing several problems that are related,
> > it would really be a shame not to solve them with a good enough framework.
> 
> well, I've been working on DSI panel support in msm drm, and also been
> looking at the patches to add DSI support in i915.  And the panel
> interface ends up looking basically like the drm_bridge interface.
> Perhaps the only thing not generic there is the name.
> 
> >> I mean, take a DSI panel driver, for example.. anything but a trivial panel
> >> driver, you are going to want to expose some custom properties on the
> >> connector for controlling non-standard features. So you end up with both
> >> cdf_foo for the common part, and drm_foo for gluing in the properties. And
> >> now these two parts which otherwise would be one, end up having to stay in
> >> sync merged through different trees, etc. It seems a lot like making my life
> >> more difficult for a fairly hypothetical gain ;-)
> >
> > The DSI panel driver should not be split into two parts. It should implement a
> > CDF entity, any glue needed for DRM will not be part of the panel driver.
> 
> right, but that glue ends up needing to be *somewhere*, which makes it
> the 2nd part.
> 
> >> Or, take an hdmi or DP bridge. To use any of the common
> >> infrastructure/helpers in drm, you end up implementing a generic interface,
> >> where both the producer and consumer is inside drm. Which just seems a bit
> >> pointless and extra hoops to jump through. Especially when we discover that
> >> we need to extend/enhance the common interface outside of drm to make it
> >> work. (I'm thinking of display_entity_control_ops::get_modes() here, but I'm
> >> sure there are more examples.) And I think we'll run into similar issues
> >> with display_entity_control_ops::set_state(), since the on<->off sequencing
> >> can get hairy when the upstream/downstream entity is fed a clk by the
> >> downstream/upstream entity. And similarly, I think we'll go through a few
> >> revisions of DSI panel/bus params before we have everything that everyone
> >> needs.
> >
> > I don't see where needing multiple revisions of a patch set would be bad :-)
> 
> I mean over multiple kernel revisions, as people start adding support
> for new hw and run into limitations of the "framework".

A framework can be changed, extended and fixed. In the end we talking
about a completely in-kernel framework for which we do not have to
maintain a stable API.

> 
> We've already figured out that just having enable() and disable() is
> not sufficient for displayport link training.  I'm not sure what else
> we'll discover.

It's pretty much expected that other things will be discovered, but this
will also happen with all sub-drm-driver frameworks we currently have.

> 
> I'm not saying not to solve (most of these) problems.. I don't think
> chaining multiple drm_bridge's is impossible, I can think of at least
> two ways to implement it.  But I think we should solve that as someone
> is adding support for hw that uses this.  This (a) lets us break
> things up into smaller more incremental changes (drm_bridge is
> *considerably* smaller than the current CDF patchset), and (b) avoids
> us solving the wrong problems.
> 
> btw, I think DT bindings is orthogonal to this discussion.

Not really. The common display framework is about splitting the pipeline
into its components and adding a common view to the components. It's CDF
helper code that can translate a DT binding directly into a encoder
pipeline.

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 06/19] video: display: OF support
  2013-08-21  1:02     ` Laurent Pinchart
@ 2013-08-21  9:10       ` Philipp Zabel
  2013-08-22  0:51         ` Laurent Pinchart
  0 siblings, 1 reply; 83+ messages in thread
From: Philipp Zabel @ 2013-08-21  9:10 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Laurent Pinchart, Tom Gall, Kyungmin Park, Tomi Valkeinen,
	linux-media, Stephen Warren, Mark Zhang, Stéphane Marchesin,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

Hi Laurent,

Am Mittwoch, den 21.08.2013, 03:02 +0200 schrieb Laurent Pinchart:
> Hi Philipp,
> 
> On Tuesday 13 August 2013 16:37:07 Philipp Zabel wrote:
> > Hi Laurent,
> > 
> > thanks for this update. I'm very happy about the move to the display entity
> > model, given that the i.MX6 IPU has both drm/display and v4l2/capture ports
> > in a single device - this will allow to use a unified device tree binding
> > scheme.
> 
> Thanks for the support :-)
> 
> > I'm still trying to see how this all fits together, so far I have only one
> > comment, below.
> > 
> > Am Freitag, den 09.08.2013, 19:14 +0200 schrieb Laurent Pinchart:
> > [...]
> > 
> > > +static int display_of_parse_dt(struct display_entity_notifier *notifier,
> > > +			       struct list_head *entities,
> > > +			       struct device_node *node)
> > > +{
> > > +	struct display_entity_of *entity;
> > > +	struct device_node *remote;
> > > +	struct device_node *ep = NULL;
> > > +	struct device_node *next;
> > > +	unsigned int num_entities = 0;
> > > +	int ret = 0;
> > > +
> > > +	/* Walk the device tree and build a list of nodes. */
> > > +	dev_dbg(notifier->dev, "parsing node %s\n", node->full_name);
> > > +
> > > +	while (1) {
> > > +		next = display_of_get_next_endpoint(node, ep);
> > > +		if (next == NULL)
> > > +			break;
> > > +
> > > +		of_node_put(ep);
> > > +		ep = next;
> > > +
> > > +		dev_dbg(notifier->dev, "handling endpoint %s\n", ep->full_name);
> > > +
> > > +		remote = display_of_get_remote_port_parent(ep);
> > > +		if (remote == NULL)
> > > +			continue;
> > > +
> > > +		/* Skip entities that we have already processed. */
> > > +		if (display_of_find_entity(entities, remote) || remote == node) {
> > > +			dev_dbg(notifier->dev,
> > > +				"entity %s already in list, skipping\n",
> > > +				remote->full_name);
> > > +			continue;
> > > +		}
> > 
> > device tree nodes with status = "disabled" should be skipped here:
> > 
> >                 if (!of_device_is_available(remote)) {
> >                         dev_dbg(notifier->dev,
> >                                 "entity %s is disabled, skipping\n",
> >                                 remote->full_name);
> >                         continue;
> >                 }
> > 
> > Otherwise the completion notification will never be delivered if there
> > are any disabled entities in the graph.
> 
> That's a good point, but if a device is disabled, why would it be in the DT 
> graph in the first place ? Do you have a use case for this ?

This is mostly about separate encoders inside the SoC, which are always
present but not useful unless the board designer connected something to
the external pads. Those might be contained in the SoC .dtsi but have
status = "disabled" set for board device tree writers' convenience.
My use case would be the LVDS encoder bridge or the Synopsys Designware
HDMI TX on i.MX6.

regards
Philipp

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
  2013-08-21  7:09       ` Sascha Hauer
@ 2013-08-21 12:22         ` Rob Clark
  2013-09-06 16:16           ` Laurent Pinchart
  2013-09-09 12:12           ` Tomi Valkeinen
  0 siblings, 2 replies; 83+ messages in thread
From: Rob Clark @ 2013-08-21 12:22 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Linux Fbdev development list, Benjamin Gaignard, dri-devel,
	Jesse Barnes, Laurent Pinchart, Sebastien Guiriec,
	Laurent Pinchart, Tom Gall, Ragesh Radhakrishnan, Tomi Valkeinen,
	linux-media, Stephen Warren, Mark Zhang, Stéphane Marchesin,
	Alexandre Courbot, Thomas Petazzoni, Sunil Joshi, Kyungmin Park

On Wed, Aug 21, 2013 at 3:09 AM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
> On Tue, Aug 20, 2013 at 02:40:55PM -0400, Rob Clark wrote:
>> On Tue, Aug 20, 2013 at 11:24 AM, Laurent Pinchart
>> <laurent.pinchart@ideasonboard.com> wrote:
>> > Hi Rob,
>> >
>> >> Or maybe, put another way, I still think we should still optimize for the
>> >> common case. I mean I'm sure you *can* design hw that has an LVDS->DP bridge
>> >> in the capture path, and if you had something like an FPGA where that was
>> >> cheap to do maybe you even would (for fun). But if in the real world, there
>> >> are only one or two cases of actual hw using the same bridge in a capture
>> >> pipeline which is normally used in display pipelines, then duplicating some
>> >> small bit of code for that abnormal case if it makes things easier for the
>> >> common case, seems like a reasonable trade-off to me.
>> >
>> > That was my opinion as well until I started working on a Xilinx platform.
>> > There's dozens of IP cores there that are used in both capture and display
>> > pipelines.
>>
>> or maybe just some helper lib's to handling the register level programming?
>>
>> Anyways, I guess you can call it a "worse is better" thing, but if you
>> can get 90% of the desired effect for 10% of the work, take the
>> simpler solution.  I don't think we should make things more layered or
>> more difficult for one exceptional case.
>>
>>
>> > Furthermore, FPGA display pipelines being made of individual IP cores, we need
>> > a way to write one driver per IP core and make them all interact. The recently
>> > proposed drm_bridge is one possible solution to this issue (and to a different
>> > but similar issue that trigerred the development of drm_bridge), but it's in
>> > my opinion not generic enough. We're facing several problems that are related,
>> > it would really be a shame not to solve them with a good enough framework.
>>
>> well, I've been working on DSI panel support in msm drm, and also been
>> looking at the patches to add DSI support in i915.  And the panel
>> interface ends up looking basically like the drm_bridge interface.
>> Perhaps the only thing not generic there is the name.
>>
>> >> I mean, take a DSI panel driver, for example.. anything but a trivial panel
>> >> driver, you are going to want to expose some custom properties on the
>> >> connector for controlling non-standard features. So you end up with both
>> >> cdf_foo for the common part, and drm_foo for gluing in the properties. And
>> >> now these two parts which otherwise would be one, end up having to stay in
>> >> sync merged through different trees, etc. It seems a lot like making my life
>> >> more difficult for a fairly hypothetical gain ;-)
>> >
>> > The DSI panel driver should not be split into two parts. It should implement a
>> > CDF entity, any glue needed for DRM will not be part of the panel driver.
>>
>> right, but that glue ends up needing to be *somewhere*, which makes it
>> the 2nd part.
>>
>> >> Or, take an hdmi or DP bridge. To use any of the common
>> >> infrastructure/helpers in drm, you end up implementing a generic interface,
>> >> where both the producer and consumer is inside drm. Which just seems a bit
>> >> pointless and extra hoops to jump through. Especially when we discover that
>> >> we need to extend/enhance the common interface outside of drm to make it
>> >> work. (I'm thinking of display_entity_control_ops::get_modes() here, but I'm
>> >> sure there are more examples.) And I think we'll run into similar issues
>> >> with display_entity_control_ops::set_state(), since the on<->off sequencing
>> >> can get hairy when the upstream/downstream entity is fed a clk by the
>> >> downstream/upstream entity. And similarly, I think we'll go through a few
>> >> revisions of DSI panel/bus params before we have everything that everyone
>> >> needs.
>> >
>> > I don't see where needing multiple revisions of a patch set would be bad :-)
>>
>> I mean over multiple kernel revisions, as people start adding support
>> for new hw and run into limitations of the "framework".
>
> A framework can be changed, extended and fixed. In the end we talking
> about a completely in-kernel framework for which we do not have to
> maintain a stable API.

oh sure, this is why I'd be absolutely against exposing this to
userspace currently..

But my only point here was that an in-drm framework, all the fix-ups
due to a framework change are sorted out before Dave sends his pull
req to linus.  We do this on a semi-regular basis already in drm
already.

Anyways, not a show-stopper thing.. just (in my mind) one additional
inconvenience (and not really the biggest one) about having the
"framework" outside of drm.  I'm more concerned about just having the
"display entity" code at a layer below the helpers and property api's
that I'd like to use in drm.

And just to be clear, part of my negative experience about this is the
omapdss/omapdrm split.  I just see cfd outside of drm as encouraging
others to make the same mistake.

>>
>> We've already figured out that just having enable() and disable() is
>> not sufficient for displayport link training.  I'm not sure what else
>> we'll discover.
>
> It's pretty much expected that other things will be discovered, but this
> will also happen with all sub-drm-driver frameworks we currently have.

right, which is why I want to "optimize" for this case by having
everything effected by evolving the framework merged via drm.

>>
>> I'm not saying not to solve (most of these) problems.. I don't think
>> chaining multiple drm_bridge's is impossible, I can think of at least
>> two ways to implement it.  But I think we should solve that as someone
>> is adding support for hw that uses this.  This (a) lets us break
>> things up into smaller more incremental changes (drm_bridge is
>> *considerably* smaller than the current CDF patchset), and (b) avoids
>> us solving the wrong problems.
>>
>> btw, I think DT bindings is orthogonal to this discussion.
>
> Not really. The common display framework is about splitting the pipeline
> into its components and adding a common view to the components. It's CDF
> helper code that can translate a DT binding directly into a encoder
> pipeline.

yes, DT binding are orthogonal.  This is something that should work
for BIOS, ACPI, DT, fex (just kidding), etc.  I mean there might be
some DT helpers, but that should be kind of on the side.

If DT binding are really to be OS independent, we probably need some
better way to deal w/ collecting up DT nodes for one (userspace
visible) driver (or cases where driver <-> DT is not 1<->1).  But that
is really an entirely different topic, or at least not applicable to
where the "framework" lives.

BR,
-R

> Sascha
>
>
> --
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 06/19] video: display: OF support
  2013-08-21  9:10       ` Philipp Zabel
@ 2013-08-22  0:51         ` Laurent Pinchart
  0 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2013-08-22  0:51 UTC (permalink / raw)
  To: Philipp Zabel
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Laurent Pinchart, Tom Gall, Kyungmin Park, Tomi Valkeinen,
	linux-media, Stephen Warren, Mark Zhang, Stéphane Marchesin,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Jo shi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

Hi Philipp,

On Wednesday 21 August 2013 11:10:12 Philipp Zabel wrote:
> Am Mittwoch, den 21.08.2013, 03:02 +0200 schrieb Laurent Pinchart:
> > On Tuesday 13 August 2013 16:37:07 Philipp Zabel wrote:
> > > Hi Laurent,
> > > 
> > > thanks for this update. I'm very happy about the move to the display
> > > entity model, given that the i.MX6 IPU has both drm/display and
> > > v4l2/capture ports> in a single device - this will allow to use a
> > > unified device tree binding scheme.
> > 
> > Thanks for the support :-)
> > 
> > > I'm still trying to see how this all fits together, so far I have only
> > > one comment, below.
> > > 
> > > Am Freitag, den 09.08.2013, 19:14 +0200 schrieb Laurent Pinchart:
> > > [...]
> > > 
> > > > +static int display_of_parse_dt(struct display_entity_notifier
> > > > *notifier,
> > > > +			       struct list_head *entities,
> > > > +			       struct device_node *node)
> > > > +{
> > > > +	struct display_entity_of *entity;
> > > > +	struct device_node *remote;
> > > > +	struct device_node *ep = NULL;
> > > > +	struct device_node *next;
> > > > +	unsigned int num_entities = 0;
> > > > +	int ret = 0;
> > > > +
> > > > +	/* Walk the device tree and build a list of nodes. */
> > > > +	dev_dbg(notifier->dev, "parsing node %s\n", node->full_name);
> > > > +
> > > > +	while (1) {
> > > > +		next = display_of_get_next_endpoint(node, ep);
> > > > +		if (next == NULL)
> > > > +			break;
> > > > +
> > > > +		of_node_put(ep);
> > > > +		ep = next;
> > > > +
> > > > +		dev_dbg(notifier->dev, "handling endpoint %s\n", ep->full_name);
> > > > +
> > > > +		remote = display_of_get_remote_port_parent(ep);
> > > > +		if (remote == NULL)
> > > > +			continue;
> > > > +
> > > > +		/* Skip entities that we have already processed. */
> > > > +		if (display_of_find_entity(entities, remote) || remote == node) {
> > > > +			dev_dbg(notifier->dev,
> > > > +				"entity %s already in list, skipping\n",
> > > > +				remote->full_name);
> > > > +			continue;
> > > > +		}
> > > 
> > > device tree nodes with status = "disabled" should be skipped here:
> > >                 if (!of_device_is_available(remote)) {
> > >                         dev_dbg(notifier->dev,
> > >                                 "entity %s is disabled, skipping\n",
> > >                                 remote->full_name);
> > >                         continue;
> > >                 }
> > > 
> > > Otherwise the completion notification will never be delivered if there
> > > are any disabled entities in the graph.
> > 
> > That's a good point, but if a device is disabled, why would it be in the
> > DT graph in the first place ? Do you have a use case for this ?
> 
> This is mostly about separate encoders inside the SoC, which are always
> present but not useful unless the board designer connected something to
> the external pads. Those might be contained in the SoC .dtsi but have
> status = "disabled" set for board device tree writers' convenience.
> My use case would be the LVDS encoder bridge or the Synopsys Designware
> HDMI TX on i.MX6.

My point was that, if a DT node is disabled, it should not be linked in a CDF 
graph in DT. However, I agree that it's easier to express the in-SoC links in 
the .dtsi files, so you've got a point. I'll integrate the change in v4.

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 08/19] video: display: Add MIPI DBI bus support
  2013-08-09 17:14 ` [PATCH/RFC v3 08/19] video: display: Add MIPI DBI bus support Laurent Pinchart
  2013-08-14  0:52   ` Rob Clark
@ 2013-08-26 11:10   ` Tomi Valkeinen
  2013-09-06 14:09     ` Laurent Pinchart
  2013-09-04 10:50   ` Vikas Sajjan
  2013-09-04 12:52   ` Vikas Sajjan
  3 siblings, 1 reply; 83+ messages in thread
From: Tomi Valkeinen @ 2013-08-26 11:10 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Stéphane Marchesin, Alexandre Courbot, Ragesh Radhakrishnan,
	Thomas Petazzoni, Sunil Joshi, Maxime Ripard, Vikas Sajjan,
	Marcus Lorentzon


[-- Attachment #1.1: Type: text/plain, Size: 1291 bytes --]

Hi,

On 09/08/13 20:14, Laurent Pinchart wrote:
> MIPI DBI is a configurable-width parallel display bus that transmits
> commands and data.
> 
> Add a new DBI Linux bus type that implements the usual bus
> infrastructure (including devices and drivers (un)registration and
> matching, and bus configuration and access functions).

This has been discussed before, but I don't remember that the issue
would have been cleared, so I'm bringing it up again.

What benefit does a real Linux DBI (or DSI) bus give us, compared to
representing the DBI the same way as DPI? DBI & DSI are in practice
point-to-point buses, and they do not support probing. Is it just that
because DBI and DSI can be used to control a device, they have to be
Linux buses?

How do you see handling the devices where DBI or DSI is used for video
only, and the control is handled via, say, i2c? The module has to
register two drivers, and try to keep those in sync? I feel that could
get rather hacky.

A real Linux bus would be necessary if we had devices that used DBI or
DSI only for control, and some other video bus for video data. But that
sounds so silly that I think we can just forget about the case. Thus DBI
and DSI are used either for video only, or video and control.

 Tomi



[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 02/19] video: Add Common Display Framework core
  2013-08-09 17:14 ` [PATCH/RFC v3 02/19] video: Add Common Display Framework core Laurent Pinchart
@ 2013-09-02  8:42   ` Tomi Valkeinen
  2013-09-03 11:29     ` Laurent Pinchart
  0 siblings, 1 reply; 83+ messages in thread
From: Tomi Valkeinen @ 2013-09-02  8:42 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon


[-- Attachment #1.1: Type: text/plain, Size: 809 bytes --]

Hi,

On 09/08/13 20:14, Laurent Pinchart wrote:
> The Common Display Framework (CDF) splits display devices in entities
> that interact through an abstract API. Each entity is managed by its own
> driver independently of the other entities, with the framework
> orchestrating interactions.
> 
> This commit introduces the CDF core with entity (un)registration and
> core control operations support.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>

The media entity code used in CDF needs (at least) MEDIA_CAMERA_SUPPORT
and MEDIA_CONTROLLER to be enabled in the kernel config. These are not
selected/depended upon currently. And while MEDIA_CONTROLLER makes
sense, MEDIA_CAMERA_SUPPORT doesn't, so maybe there's some tuning needed
for the media code.

 Tomi




[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
  2013-08-09 17:14 [PATCH/RFC v3 00/19] Common Display Framework Laurent Pinchart
                   ` (19 preceding siblings ...)
  2013-08-14  0:43 ` [PATCH/RFC v3 00/19] " Rob Clark
@ 2013-09-02 11:06 ` Tomi Valkeinen
  2013-09-30 13:48 ` Tomi Valkeinen
  21 siblings, 0 replies; 83+ messages in thread
From: Tomi Valkeinen @ 2013-09-02 11:06 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon


[-- Attachment #1.1: Type: text/plain, Size: 23058 bytes --]

On 09/08/13 20:14, Laurent Pinchart wrote:
> Hi everybody,
> 
> Here's the third RFC of the Common Display Framework.
> 
> I won't repeat all the background information from the versions one and two
> here, you can read it at http://lwn.net/Articles/512363/ and
> http://lwn.net/Articles/526965/.
> 
> This RFC isn't final. Given the high interest in CDF and the urgent tasks that
> kept delaying the next version of the patch set, I've decided to release v3
> before completing all parts of the implementation. Known missing items are
> 
> - documentation: kerneldoc and this cover letter should provide basic
>   information, more extensive documentation will likely make it to v4.
> 
> - pipeline configuration and control: generic code to configure and control
>   display pipelines (in a nutshell, translating high-level mode setting and
>   DPMS calls to low-level entity operations) is missing. Video and stream
>   control operations have been carried over from v2, but will need to be
>   revised for v4.
> 
> - DSI support: I still have no DSI hardware I can easily test the code on.
> 
> Special thanks go to
> 
> - Renesas for inviting me to LinuxCon Japan 2013 where I had the opportunity
>   to validate the CDF v3 concepts with Alexandre Courbot (NVidia) and Tomasz
>   Figa (Samsung).
> 
> - Tomi Valkeinen (TI) for taking the time to deeply brainstorm v3 with me.
> 
> - Linaro for inviting me to Linaro Connect Europe 2013, the discussions we had
>   there greatly helped moving CDF forward.
> 
> - And of course all the developers who showed interest in CDF and spent time
>   sharing ideas, reviewing patches and testing code.
> 
> I have to confess I was a bit lost and discouraged after all the CDF-related
> meetings during which we have discussed how to move from v2 to v3. With every
> meeting I was hoping to run the implementation through use cases of various
> interesting parties and narrow down the scope of the huge fuzzy beast that CDF
> was. With every meeting the scope actually broadened, with no clear path at
> sight anywhere.
> 
> Earlier this year I was about to drop one of the requirements on which I had
> based CDF v2: sharing drivers between DRM/KMS and V4L2. With only two HDMI
> transmitters as use cases for that feature (with only out-of-tree drivers so
> far), I just thought the involved completely wasn't worth it and that I should
> implement CDF v3 as a DRM/KMS-only helper framework. However, a seemingly
> unrelated discussion with Xilinx developers showed me that hybrid SoC-FPGA
> platforms such as the Xilinx Zynq 7000 have a larger library of IP cores that
> can be used in camera capture pipelines and in display pipelines. The two use
> cases suddenly became tens or even hundreds of use cases that I couldn't
> ignore anymore.

Should this be Common Video Framework then? ;)

> CDF v3 is thus userspace API agnostic. It isn't tied to DRM/KMS or V4L2 and
> can be used by any kernel subsystem, potentially including FBDEV (although I
> won't personally wrote FBDEV support code, as I've already advocated for FBDEV
> to be deprecated).
> 
> The code you are about to read is based on the concept of display entities
> introduced in v2. Diagrams related to the explanations below are available at
> http://ideasonboard.org/media/cdf/20130709-lce-cdf.pdf.
> 
> 
> Display Entities
> ----------------
> 
> A display entity abstracts any hardware block that sources, processes or sinks
> display-related video streams. It offers an abstract API, implemented by display
> entity drivers, that is used by master drivers (such as the main display driver)
> to query, configure and control display pipelines.
> 
> Display entities are connected to at least one video data bus, and optionally
> to a control bus. The video data busses carry display-related video data out
> of sources (such as a CRTC in a display controller) to sinks (such as a panel
> or a monitor), optionally going through transmitters, encoders, decoders,
> bridges or other similar devices. A CRTC or a panel will usually be connected
> to a single data bus, while an encoder or a transmitter will be connected to
> two data busses.
> 
> The simple linear display pipelines we find in most embedded platforms at the
> moment are expected to grow more complex with time. CDF needs to accomodate
> those needs from the start to be, if not future-proof, at least present-proof
> at the time it will get merged in to mainline. For this reason display
> entities have data ports through which video streams flow in or out, with link
> objects representing the connections between those ports. A typical entity in
> a linear display pipeline will have one (for video source and video sink
> entities such as CRTCs or panels) or two ports (for video processing entities
> such as encoders), but more ports are allowed, and entities can be linked in
> complex non-linear pipelines.
> 
> Readers might think that this model if extremely similar to the media
> controller graph model. They would be right, and given my background this is
> most probably not a coincidence. The CDF v3 implementation uses the in-kernel
> media controller framework to model the graph of display entities, with the
> display entity data structure inheriting from the media entity structure. The
> display pipeline graph topology will be automatically exposed to userspace
> through the media controller API as an added bonus. However, ussage of the
> media controller userspace API in applications is *not* mandatory, and the
> current CDF implementation doesn't use the media controller link setup
> userspace API to configure the display pipelines.

I have yet to look at the code. I'm just wondering, do you see any
downsides on using the media controller here, instead a CDF specific entity?

> While some display entities don't require any configuration (DPI panels are a
> good example), many of them are connected to a control bus accessible to the
> CPU. Control requests can be sent on a dedicated control bus (such as I2C or
> SPI) or multiplexed on a mixed control and data bus (such as DBI or DSI). To
> support both options the CDF display entity model separates the control and
> data busses in different APIs.
> 
> Display entities are abstract object that must be implemented by a real
> device. The device sits on its control bus and is registered with the Linux
> device core and matched with his driver using the control bus specific API.
> The CDF doesn't create a display entity class or bus, display entity drivers
> thus standard Linux kernel drivers using existing busses. A DBI bus is added

I have no idea what the above means =). I guess the point is that CDF
doesn't create the display entities or devices or busses. It's the
standard linux drivers will create CDF display entities?

> as part of this patch set, but strictly speaking this isn't part of CDF.
> 
> When a display entity driver probes a device it must create an instance of the
> display_entity structure, initialize it and add it to the CDF core entities
> pool. The display entity exposes abstract operations through function
> pointers, and the entity driver must implement those operations. Those
> operations can act on either the whole entity or on a given port, depending on
> the operation. They are divided in two groups, control operations and video
> operations.
> 
> 
> Control Operations
> ------------------
> 
> Control operations are called by upper-level drivers, usually in response to a
> request originating from userspace. They query or control the display entity
> state and operation. Currently defined control operations are
> 
> - get_size(), to retrieve the entity physical size (applicable to panels only)
> - get_modes(), to retrieve the video modes supported at an entity port
> - get_params(), to retrieve the data bus parameters at an entity port
> 
> - set_state(), to control the state of the entity (off, standby or on)
> - update(), to trigger a display update (for entities that implement manual
>   update, such as manual-update panels that store frames in their internal
>   frame buffer)
> 
> The last two operations have been carried from v2 and will be reworked.
> 
> 
> Pipeline Control
> ----------------
> 
> The figure on page 4 shows the control model for a linear pipeline. This
> differs significantly from CDF v2 where calls where forwarded from entity to
> entity using a Russian dolls model. v3 removes the need of neighbour awareness
> from entity drivers, simplifying the entity drivers. The complexity of pipeline
> configuration is moved to a central location called a pipeline controller
> instead of being spread out to all drivers.
> 
> Pipeline controllers provide library functions that display drivers can use to
> control a pipeline. Several controllers can be implemented to accomodate the
> needs of various pipeline topologies and complexities, and display drivers can
> even implement their own pipeline control algorithm if needed. I'm working on a
> linear pipeline controller for the next version of the patch set.
> 
> If pipeline controllers are responsible for propagating a pipeline configuration
> on all entity ports in the pipeline, entity drivers are responsible for
> propagating the configuration inside entities, from sink (input) to source
> (output) ports as illustrated on page 5. The rationale behind this is that
> knowledge of the entity internals is located in the entity driver, while
> knowledge of the pipeline belongs to the pipeline controller. The controller
> will thus configure the pipeline by performing the following steps:
> 
> - applying a configuration on sink ports of an entity
> - read the configuration that has been propagated by the entity driver on its
>   source ports
> - optionally, modify the source port configuration (to configure custom timings,
>   scaling or other parameters, if supported by the entity)
> - propagate the source port configuration to the sink ports of the next entities
>   in the pipeline and start over

First, I find "sink" and "source" somewhat confusing here. Maybe it's
just me... If I understand correctly, "sink port of an entity" means a
port on an entity which is receiving data, so, say, the port on a panel.
And "source port of an entity" is a port to which an entity writes data.

Wouldn't "input port" and "output port" be more clear?

Another thing. We have discussed this a few times, and also discussed it
the last time you were in Helsinki. But it's still a bit unclear to me
should the configuration go "downstream", as you describe, or
"upstream", as the omapdss does.

If we look at a single entity in the pipeline, I think we can describe
the two different approaches like this:

Downstream model: "Hey entity, here's the video format you will be
getting. What kind of output video format do you give for that input?"

Upstream model: "Hey entity, we need this video output from you. What
kind of input do you need to produce the output?"

I think both models have complexities/issues, but if I forget the
issues, I think the upstream model is more powerful, and maybe even more
"correct":

In the end of the pipeline, we have a monitor or a panel. We want the
monitor/panel to show a picture with some particular video mode. So the
job for the pipeline controller is to find out settings for each display
entity to produce that video mode in the end. With the downstream model
you'll start from the SoC side with some video mode, and hope that the
end result will be what's needed by the monitor/panel.

As an example, DSI video mode on OMAP (although I think the same applies
to any other SoC with DSI). The pipeline we have is like this, ->
showing the video data flow:

DISPC -> DSI -> Panel

The DISPC-DSI link is raw parallel RGB.

With the DSI transfer we can have either burst or non-burst mode. When
in non-burst mode, the DSI transfer looks pretty much like normal
parallel RGB, except that it's in serial format.

With burst mode, however, the DSI clock and horizontal timings can be
changed. The idea with burst mode is to increase the time spent in
horizontal blank period, thus reducing the time the DISPC and DSI blocks
need to be active. So we could, say, double the DSI clock, and increase
the horizontal blank accordingly.

What this means in the context of pipeline configuration is that the
DISPC needs to be configured properly to produce pixels for the DSI. If
the DSI clock and horizontal blank are increased, the DISPC pixel clock
and blank need to be increased also.

Even in non-burst mode the video mode programmed to DISPC is not always
quite the as the resulting video mode received by the panel, because the
DISPC uses pixel clock and the transfer unit is a pixel, DSI uses DSI
bus clock and a transfer unit is a byte, and these are not always in
1-to-1 match. So if one wants exactly certain DSI video mode timings,
this discrepancy needs to be taken into consideration when programming
DISPC timings.

Then again, as I said, upstream model is not without its issues either.
Say, if we want a particular output from DSI, with burst mode. The DSI
should somehow know how high pixel clock and horizontal timings DISPC
can produce before it can calculate the video mode.

I guess the only way to avoid the issues is to add all this logic into
the pipeline control? And if so, then it doesn't really matter if the
configuration is done with downstream or upstream model.

I fear a bit that adding this kind of logic into the controller means we
will add display entity specific things into the controllers. So if I
create a generic OMAP pipeline controller, which works for all the
currnet boards, and then somebody creates a new OMAP board with some
funny encoder, he'll have to create a new controller, almost like the
generic OMAP one, but with support for the funny encoder.

> Beside modifying the active configuration, the entities API will allow trying
> configurations without applying them to the hardware. As configuration of a port
> possibly depend on the configurations of the other ports, trying a configuration
> must be done at the entity level instead of the port level. The implementation
> will be based on the concept of configuration store objects that will store the
> configuration of all ports for a given entity. Each entity will have a single
> active configuration store, and test configuration stores will be created
> dynamically to try a configuration on an entity. The get and set operations
> implemented by the entity will receive a configuration store pointer, and active
> and test code paths in entity drivers will be identical, except for applying the
> configuration to the hardware for the active code path.
> 
> 
> Video Operations
> ----------------
> 
> Video operations control the video stream state on entity ports. The only
> currently defined video operation is
> 
> - set_stream(), to start (in continuous or single-shot mode) the video stream
>   on an entity port
> 
> The call model for video operations differ from the control operations model
> described above. The set_stream() operation is called directly by downstream
> entities on upstream entities (from a video data bus point of view).
> Terminating entities in a pipeline (such as panels) will usually call the
> set_stream() operation in their set_state() handler, and intermediate entities
> will forward the set_stream() call upstream.
> 
> 
> Integration
> -----------
> 
> The figure on page 8 describes how a panel driver, implemented using CDF as a
> display entity, interacts with the other components in the system. The use case
> is a simple pipeline made of a display controller and a panel.
> 
> The display controller driver receives control request from userspace through
> DRM (or FBDEV) API calls. It processes the request and calls the panel driver
> through the CDF control operations API. The panel driver will then issue
> requests on its control bus (several possible control busses are shown on the
> figure, panel drivers typically use one of them only) and call video operations
> of the display controller on its left side to control the video stream.
> 
> 
> Registration and Notification
> -----------------------------
> 
> Due to possibly complex dependencies between entities we can't guarantee that
> all entities part of the display pipeline will have been successfully probed
> when the master display controller driver is probed. For instance a panel can
> be a child of the DBI or DSI bus controlled by the display device, or use a
> clock provided by that device. We can't defer the display device probe until
> the panel is probed and also defer the panel device probe until the display
> device is probed. For this reason we need a notification system that allows
> entities to register themselves with the CDF core, and display controller
> drivers to get notified when entities they need are available.

I don't understand this one. Do you have a example setup that shows the
problem?

I think we can just use the EPROBE_DEFER here. A display entity requires
some resources, like GPIOs and regulators, and with CDF, video sources.
If those resources are not yet available, the driver can just return
EPROBE_DEFER.

Or is there some kind of two-way dependency in your model, when using
DBI? We don't have such in omapdss, so I may not quite understand the
issue or the need for the two-way dependency.

The only case where I can see a dependency problem is when two display
entities produce a resource, used by the other. So, say, we have an
encoder and a panel, and the panel produces a clock used by the encoder,
and the encoder produces a video signal used by the panel. I haven't
seen such setups in real hardware, though

> The notification system has been completely redesigned in v3. This version is
> based on the V4L2 asynchronous probing notification code, with large parts of
> the code shamelessly copied. This is an interim solution to let me play with
> the notification code as needed by CDF. I'm not a fan of code duplication, and
> will work on merging the CDF and V4L2 implementations in a later stage when
> CDF will reach a mature enough state.
> 
> CDF manages a pool of entities and a list of notifiers. Notifiers are
> registered by master display drivers with an array of entities match
> descriptors. When an entity is added to the CDF entities pool, all notifiers
> are searched for a match. If a match is found, the corresponding notifier is
> called to notify the master display driver.
> 
> The two currently supported match methods are platform match, which uses
> device names, and DT match, which uses DT node pointers. More match method
> might be added later if needed. Two helper functions exist to build a notifier
> from a list of platform device names (in the non-DT case) or a DT
> representation of the display pipeline topology.
> 
> Once all required entities have been successfully found, the master display
> driver is responsible for creating media controller links between all entities
> in the pipeline. Two helper functions are also available to automate that
> process, one for the non-DT case and one for the DT case. Once again some
> DT-related code has been copied from the V4L2 DT code, I will work on merging
> both in a future version.
> 
> Note that notification brings a different issue after registration, as display
> controller and display entity drivers would take a reference to each other.
> Those circular references would make driver unloading impossible. One possible
> solution to this problem would be to simulate an unplug event for the display
> entity, to force the display driver to release the dislay entities it uses. We
> would need a userspace API for that though. Better solutions would of course
> be welcome.
> 
> 
> Device Tree Bindings
> --------------------
> 
> CDF entities device tree bindings are not documented yet. They describe both
> the graph topology and entity-specific information. The graph description uses
> the V4L2 DT bindings (which are actually not V4L2-specific) specified at
> Documentation/devicetree/bindings/media/video-interfaces.txt. Entity-specific
> information will be described in individual DT bindings documentation. The DPI
> panel driver uses the display timing bindings documented in
> Documentation/devicetree/bindings/video/display-timing.txt.
> 
> 
> 
> 
> Please note that most of the display entities on devices I own are just dumb
> panels with no control bus, and are thus not the best candidates to design a
> framework that needs to take complex panels' needs into account. This is why I
> hope to see you using the CDF with your display device and tell me what needs to
> be modified/improved/redesigned.
> 
> This patch set is split as follows:
> 
> - The first patch fixes a Kconfig namespace issue with the OMAP DSS panels. It
>   could be applied already independently of this series.
> - Patches 02/19 to 07/19 add the CDF core, including the notification system
>   and the graph and OF helpers.
> - Patch 08/19 adds a MIPI DBI bus. This isn't part of CDF strictly speaking,
>   but is needed for the DBI panel drivers.
> - Patches 09/19 to 13/19 add panel drivers, a VGA DAC driver and a VGA
>   connector driver.
> - Patches 14/19 to 18/19 add CDF-compliant reference board code and DT for the
>   Renesas Marzen and Lager boards.
> - Patch 19/19 port the Renesas R-Car Display Unit driver to CDF.
> 
> The patches are available in my git tree at
> 
>     git://linuxtv.org/pinchartl/fbdev.git cdf/v3
>     http://git.linuxtv.org/pinchartl/fbdev.git/shortlog/refs/heads/cdf/v3
> 
> For convenience I've included modifications to the Renesas R-Car Display Unit
> driver to use the CDF. You can read the code to see how the driver uses CDF to
> interface panels. Please note that the rcar-du-drm implementation is still
> work in progress, its set_stream operation implementation doesn't enable and
> disable the video stream yet as it should.
> 
> As already mentioned in v2, I will appreciate all reviews, comments,
> criticisms, ideas, remarks, ... If you can find a clever way to solve the
> cyclic references issue described above I'll buy you a beer at the next
> conference we will both attend. If you think the proposed solution is too
> complex, or too simple, I'm all ears, but I'll have more arguments this time
> than I had with v2 :-)

I'll tweak this to work with omapdss, like I did for the v2. Although
I'll probably remove at least the DBI bus and the notification system as
the first thing I do, unless you can convince me otherwise =).

 Tomi



[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 02/19] video: Add Common Display Framework core
  2013-09-02  8:42   ` Tomi Valkeinen
@ 2013-09-03 11:29     ` Laurent Pinchart
  0 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2013-09-03 11:29 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Laurent Pinchart, Tom Gall, Kyungmin Park, linux-media,
	Stephen Warren, Mark Zhang, Alexandre Courbot,
	Ragesh Radhakrishnan, Thomas Petazzoni, Sunil Joshi,
	Maxime Ripard, Vikas Sajjan, Marcus Lorentzon


[-- Attachment #1.1: Type: text/plain, Size: 972 bytes --]

Hi Tomi,

On Monday 02 September 2013 11:42:00 Tomi Valkeinen wrote:
> On 09/08/13 20:14, Laurent Pinchart wrote:
> > The Common Display Framework (CDF) splits display devices in entities
> > that interact through an abstract API. Each entity is managed by its own
> > driver independently of the other entities, with the framework
> > orchestrating interactions.
> > 
> > This commit introduces the CDF core with entity (un)registration and
> > core control operations support.
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> 
> The media entity code used in CDF needs (at least) MEDIA_CAMERA_SUPPORT
> and MEDIA_CONTROLLER to be enabled in the kernel config. These are not
> selected/depended upon currently.

Good point. I'll select MEDIA_CONTROLLER.

> And while MEDIA_CONTROLLER makes sense, MEDIA_CAMERA_SUPPORT doesn't, so
> maybe there's some tuning needed for the media code.

Agreed, I'll fix that.

-- 
Regards,

Laurent Pinchart

[-- Attachment #1.2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 08/19] video: display: Add MIPI DBI bus support
  2013-08-09 17:14 ` [PATCH/RFC v3 08/19] video: display: Add MIPI DBI bus support Laurent Pinchart
  2013-08-14  0:52   ` Rob Clark
  2013-08-26 11:10   ` Tomi Valkeinen
@ 2013-09-04 10:50   ` Vikas Sajjan
  2013-09-06 14:37     ` Laurent Pinchart
  2013-09-04 12:52   ` Vikas Sajjan
  3 siblings, 1 reply; 83+ messages in thread
From: Vikas Sajjan @ 2013-09-04 10:50 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-fbdev, Sebastien Guiriec, DRI mailing list, Jesse Barnes,
	Benjamin Gaignard, Tom Gall, Kyungmin Park, Tomi Valkeinen,
	linux-media, Stephen Warren, Mark Zhang, Alexandre Courbot,
	Ragesh Radhakrishnan, Thomas Petazzoni, Sunil Joshi,
	Maxime Ripard, Marcus Lorentzon

Hi Laurent,

On 9 August 2013 22:44, Laurent Pinchart
<laurent.pinchart+renesas@ideasonboard.com> wrote:
> MIPI DBI is a configurable-width parallel display bus that transmits
> commands and data.
>
> Add a new DBI Linux bus type that implements the usual bus
> infrastructure (including devices and drivers (un)registration and
> matching, and bus configuration and access functions).
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/video/display/Kconfig        |   8 ++
>  drivers/video/display/Makefile       |   1 +
>  drivers/video/display/mipi-dbi-bus.c | 234 +++++++++++++++++++++++++++++++++++
>  include/video/display.h              |   4 +
>  include/video/mipi-dbi-bus.h         | 125 +++++++++++++++++++
>  5 files changed, 372 insertions(+)
>  create mode 100644 drivers/video/display/mipi-dbi-bus.c
>  create mode 100644 include/video/mipi-dbi-bus.h
>
> diff --git a/drivers/video/display/Kconfig b/drivers/video/display/Kconfig
> index 1d533e7..f7532c1 100644
> --- a/drivers/video/display/Kconfig
> +++ b/drivers/video/display/Kconfig
> @@ -2,3 +2,11 @@ menuconfig DISPLAY_CORE
>         tristate "Display Core"
>         ---help---
>           Support common display framework for graphics devices.
> +
> +if DISPLAY_CORE
> +
> +config DISPLAY_MIPI_DBI
> +       tristate
> +       default n
> +
> +endif # DISPLAY_CORE
> diff --git a/drivers/video/display/Makefile b/drivers/video/display/Makefile
> index b907aad..59022d2 100644
> --- a/drivers/video/display/Makefile
> +++ b/drivers/video/display/Makefile
> @@ -1,3 +1,4 @@
>  display-y                                      := display-core.o \
>                                                    display-notifier.o
>  obj-$(CONFIG_DISPLAY_CORE)                     += display.o
> +obj-$(CONFIG_DISPLAY_MIPI_DBI)                 += mipi-dbi-bus.o
> diff --git a/drivers/video/display/mipi-dbi-bus.c b/drivers/video/display/mipi-dbi-bus.c
> new file mode 100644
> index 0000000..791fb4d
> --- /dev/null
> +++ b/drivers/video/display/mipi-dbi-bus.c
> @@ -0,0 +1,234 @@
> +/*
> + * MIPI DBI Bus
> + *
> + * Copyright (C) 2012 Renesas Solutions Corp.
> + *
> + * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> + *
> + * 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.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/export.h>
> +#include <linux/kernel.h>
> +#include <linux/list.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/pm.h>
> +#include <linux/pm_runtime.h>
> +
> +#include <video/mipi-dbi-bus.h>
> +
> +/* -----------------------------------------------------------------------------
> + * Bus operations
> + */
> +
> +int mipi_dbi_set_data_width(struct mipi_dbi_device *dev, unsigned int width)
> +{
> +       if (width != 8 && width != 16)
> +               return -EINVAL;
> +
> +       dev->data_width = width;
> +       return 0;
> +}
> +EXPORT_SYMBOL_GPL(mipi_dbi_set_data_width);
> +
> +int mipi_dbi_write_command(struct mipi_dbi_device *dev, u16 cmd)
> +{
> +       return dev->bus->ops->write_command(dev->bus, dev, cmd);
> +}
> +EXPORT_SYMBOL_GPL(mipi_dbi_write_command);
> +
> +int mipi_dbi_write_data(struct mipi_dbi_device *dev, const u8 *data,
> +                       size_t len)
> +{
> +       return dev->bus->ops->write_data(dev->bus, dev, data, len);
> +}
> +EXPORT_SYMBOL_GPL(mipi_dbi_write_data);
> +
> +int mipi_dbi_read_data(struct mipi_dbi_device *dev, u8 *data, size_t len)
> +{
> +       return dev->bus->ops->read_data(dev->bus, dev, data, len);
> +}
> +EXPORT_SYMBOL_GPL(mipi_dbi_read_data);
> +
> +/* -----------------------------------------------------------------------------
> + * Bus type
> + */
> +
> +static const struct mipi_dbi_device_id *
> +mipi_dbi_match_id(const struct mipi_dbi_device_id *id,
> +                 struct mipi_dbi_device *dev)
> +{
> +       while (id->name[0]) {
> +               if (strcmp(dev->name, id->name) == 0) {
> +                       dev->id_entry = id;
> +                       return id;
> +               }
> +               id++;
> +       }
> +       return NULL;
> +}
> +
> +static int mipi_dbi_match(struct device *_dev, struct device_driver *_drv)
> +{
> +       struct mipi_dbi_device *dev = to_mipi_dbi_device(_dev);
> +       struct mipi_dbi_driver *drv = to_mipi_dbi_driver(_drv);
> +
> +       if (drv->id_table)
> +               return mipi_dbi_match_id(drv->id_table, dev) != NULL;
> +
> +       return (strcmp(dev->name, _drv->name) == 0);
> +}
> +
> +static ssize_t modalias_show(struct device *_dev, struct device_attribute *a,
> +                            char *buf)
> +{
> +       struct mipi_dbi_device *dev = to_mipi_dbi_device(_dev);
> +       int len = snprintf(buf, PAGE_SIZE, MIPI_DBI_MODULE_PREFIX "%s\n",
> +                          dev->name);
> +
> +       return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
> +}
> +
> +static struct device_attribute mipi_dbi_dev_attrs[] = {
> +       __ATTR_RO(modalias),
> +       __ATTR_NULL,
> +};
> +
> +static int mipi_dbi_uevent(struct device *_dev, struct kobj_uevent_env *env)
> +{
> +       struct mipi_dbi_device *dev = to_mipi_dbi_device(_dev);
> +
> +       add_uevent_var(env, "MODALIAS=%s%s", MIPI_DBI_MODULE_PREFIX,
> +                      dev->name);
> +       return 0;
> +}
> +
> +static const struct dev_pm_ops mipi_dbi_dev_pm_ops = {
> +       .runtime_suspend = pm_generic_runtime_suspend,
> +       .runtime_resume = pm_generic_runtime_resume,
> +       .suspend = pm_generic_suspend,
> +       .resume = pm_generic_resume,
> +       .freeze = pm_generic_freeze,
> +       .thaw = pm_generic_thaw,
> +       .poweroff = pm_generic_poweroff,
> +       .restore = pm_generic_restore,
> +};
> +
> +static struct bus_type mipi_dbi_bus_type = {
> +       .name           = "mipi-dbi",
> +       .dev_attrs      = mipi_dbi_dev_attrs,
> +       .match          = mipi_dbi_match,
> +       .uevent         = mipi_dbi_uevent,
> +       .pm             = &mipi_dbi_dev_pm_ops,
> +};
> +
> +/* -----------------------------------------------------------------------------
> + * Device and driver (un)registration
> + */
> +
> +/**
> + * mipi_dbi_device_register - register a DBI device
> + * @dev: DBI device we're registering
> + */
> +int mipi_dbi_device_register(struct mipi_dbi_device *dev,
> +                             struct mipi_dbi_bus *bus)
> +{
> +       device_initialize(&dev->dev);
> +
> +       dev->bus = bus;
> +       dev->dev.bus = &mipi_dbi_bus_type;
> +       dev->dev.parent = bus->dev;
> +
> +       if (dev->id != -1)
> +               dev_set_name(&dev->dev, "%s.%d", dev->name,  dev->id);
> +       else
> +               dev_set_name(&dev->dev, "%s", dev->name);
> +
> +       return device_add(&dev->dev);
> +}



The function looks very much specific to NON-DT case where you will be
calling mipi_dbi_device_register() in the machine file.

I was actually trying to migrate to CDFv3 and adding MIPI DSI support
for exynos5250,
but in my case where exynos5250 is fully DT based, in which case we
need something like ./drivers/of/platform.c for MIPI DBI and MIPI DSI
to add the MIPI DBI/DSI device via DT way, ./drivers/of/mipi_dbi.c and
./drivers/of/mipi_dsi.c

may look like below,

int of_mipi_dbi_device_register(struct device_node *np,
                                         const char *bus_id,
                                         struct device *parent)
{

         struct mipi_dbi_device *dev;
         dev = of_device_alloc(np, bus_id, parent);
         if (!dev)
                 return NULL;
       device_initialize(dev);

       dev->bus = &mipi_dbi_bus_type;
       dev->parent = parent;

       return of_device_add(dev);
}

Correct me if I am wrong.



> +EXPORT_SYMBOL_GPL(mipi_dbi_device_register);
> +
> +/**
> + * mipi_dbi_device_unregister - unregister a DBI device
> + * @dev: DBI device we're unregistering
> + */
> +void mipi_dbi_device_unregister(struct mipi_dbi_device *dev)
> +{
> +       device_del(&dev->dev);
> +       put_device(&dev->dev);
> +}
> +EXPORT_SYMBOL_GPL(mipi_dbi_device_unregister);
> +
> +static int mipi_dbi_drv_probe(struct device *_dev)
> +{
> +       struct mipi_dbi_driver *drv = to_mipi_dbi_driver(_dev->driver);
> +       struct mipi_dbi_device *dev = to_mipi_dbi_device(_dev);


Here we are assuming that  mipi_dbi_device can be obtained by using
_dev pointer, which may NOT be true in DT case, i think.

let me know if i am missing something.

if you can give me a example for DT case, that would be helpful.


> +
> +       return drv->probe(dev);
> +}
> +
> +static int mipi_dbi_drv_remove(struct device *_dev)
> +{
> +       struct mipi_dbi_driver *drv = to_mipi_dbi_driver(_dev->driver);
> +       struct mipi_dbi_device *dev = to_mipi_dbi_device(_dev);
> +       int ret;
> +
> +       ret = drv->remove(dev);
> +       if (ret < 0)
> +               return ret;
> +
> +       mipi_dbi_set_drvdata(dev, NULL);
> +
> +       return 0;
> +}
> +
> +/**
> + * mipi_dbi_driver_register - register a driver for DBI devices
> + * @drv: DBI driver structure
> + */
> +int mipi_dbi_driver_register(struct mipi_dbi_driver *drv)
> +{
> +       drv->driver.bus = &mipi_dbi_bus_type;
> +       if (drv->probe)
> +               drv->driver.probe = mipi_dbi_drv_probe;
> +       if (drv->remove)
> +               drv->driver.remove = mipi_dbi_drv_remove;
> +
> +       return driver_register(&drv->driver);
> +}
> +EXPORT_SYMBOL_GPL(mipi_dbi_driver_register);
> +
> +/**
> + * mipi_dbi_driver_unregister - unregister a driver for DBI devices
> + * @drv: DBI driver structure
> + */
> +void mipi_dbi_driver_unregister(struct mipi_dbi_driver *drv)
> +{
> +       driver_unregister(&drv->driver);
> +}
> +EXPORT_SYMBOL_GPL(mipi_dbi_driver_unregister);
> +
> +/* -----------------------------------------------------------------------------
> + * Init/exit
> + */
> +
> +static int __init mipi_dbi_init(void)
> +{
> +       return bus_register(&mipi_dbi_bus_type);
> +}
> +
> +static void __exit mipi_dbi_exit(void)
> +{
> +       bus_unregister(&mipi_dbi_bus_type);
> +}
> +
> +module_init(mipi_dbi_init);
> +module_exit(mipi_dbi_exit)
> +
> +MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
> +MODULE_DESCRIPTION("MIPI DBI Bus");
> +MODULE_LICENSE("GPL");
> diff --git a/include/video/display.h b/include/video/display.h
> index ba319d6..3138401 100644
> --- a/include/video/display.h
> +++ b/include/video/display.h
> @@ -17,6 +17,7 @@
>  #include <linux/list.h>
>  #include <linux/module.h>
>  #include <media/media-entity.h>
> +#include <video/mipi-dbi-bus.h>
>
>  #define DISPLAY_PIXEL_CODING(option, type, from, to, variant) \
>         (((option) << 17) | ((type) << 13) | ((variant) << 10) | \
> @@ -189,6 +190,9 @@ enum display_entity_interface_type {
>
>  struct display_entity_interface_params {
>         enum display_entity_interface_type type;
> +       union {
> +               struct mipi_dbi_interface_params dbi;
> +       } p;
>  };
>
>  struct display_entity_control_ops {
> diff --git a/include/video/mipi-dbi-bus.h b/include/video/mipi-dbi-bus.h
> new file mode 100644
> index 0000000..876b69d
> --- /dev/null
> +++ b/include/video/mipi-dbi-bus.h
> @@ -0,0 +1,125 @@
> +/*
> + * MIPI DBI Bus
> + *
> + * Copyright (C) 2012 Renesas Solutions Corp.
> + *
> + * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> + *
> + * 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.
> + */
> +
> +#ifndef __MIPI_DBI_BUS_H__
> +#define __MIPI_DBI_BUS_H__
> +
> +#include <linux/device.h>
> +
> +struct mipi_dbi_bus;
> +struct mipi_dbi_device;
> +
> +struct mipi_dbi_bus_ops {
> +       int (*write_command)(struct mipi_dbi_bus *bus,
> +                            struct mipi_dbi_device *dev, u16 cmd);
> +       int (*write_data)(struct mipi_dbi_bus *bus, struct mipi_dbi_device *dev,
> +                         const u8 *data, size_t len);
> +       int (*read_data)(struct mipi_dbi_bus *bus, struct mipi_dbi_device *dev,
> +                        u8 *data, size_t len);
> +};
> +
> +struct mipi_dbi_bus {
> +       struct device *dev;
> +       const struct mipi_dbi_bus_ops *ops;
> +};
> +
> +#define MIPI_DBI_MODULE_PREFIX         "mipi-dbi:"
> +#define MIPI_DBI_NAME_SIZE             32
> +
> +struct mipi_dbi_device_id {
> +       char name[MIPI_DBI_NAME_SIZE];
> +       __kernel_ulong_t driver_data    /* Data private to the driver */
> +                       __aligned(sizeof(__kernel_ulong_t));
> +};
> +
> +enum mipi_dbi_interface_type {
> +       MIPI_DBI_INTERFACE_TYPE_A,
> +       MIPI_DBI_INTERFACE_TYPE_B,
> +};
> +
> +#define MIPI_DBI_INTERFACE_TE          (1 << 0)
> +
> +struct mipi_dbi_interface_params {
> +       enum mipi_dbi_interface_type type;
> +       unsigned int flags;
> +
> +       unsigned int cs_setup;
> +       unsigned int rd_setup;
> +       unsigned int rd_latch;
> +       unsigned int rd_cycle;
> +       unsigned int rd_hold;
> +       unsigned int wr_setup;
> +       unsigned int wr_cycle;
> +       unsigned int wr_hold;
> +};
> +
> +#define MIPI_DBI_FLAG_ALIGN_LEFT       (1 << 0)
> +
> +struct mipi_dbi_device {
> +       const char *name;
> +       int id;
> +       struct device dev;
> +
> +       const struct mipi_dbi_device_id *id_entry;
> +       struct mipi_dbi_bus *bus;
> +
> +       unsigned int flags;
> +       unsigned int bus_width;
> +       unsigned int data_width;
> +};
> +
> +#define to_mipi_dbi_device(d)  container_of(d, struct mipi_dbi_device, dev)
> +
> +int mipi_dbi_device_register(struct mipi_dbi_device *dev,
> +                            struct mipi_dbi_bus *bus);
> +void mipi_dbi_device_unregister(struct mipi_dbi_device *dev);
> +
> +struct mipi_dbi_driver {
> +       int(*probe)(struct mipi_dbi_device *);
> +       int(*remove)(struct mipi_dbi_device *);
> +       struct device_driver driver;
> +       const struct mipi_dbi_device_id *id_table;
> +};
> +
> +#define to_mipi_dbi_driver(d)  container_of(d, struct mipi_dbi_driver, driver)
> +
> +int mipi_dbi_driver_register(struct mipi_dbi_driver *drv);
> +void mipi_dbi_driver_unregister(struct mipi_dbi_driver *drv);
> +
> +static inline void *mipi_dbi_get_drvdata(const struct mipi_dbi_device *dev)
> +{
> +       return dev_get_drvdata(&dev->dev);
> +}
> +
> +static inline void mipi_dbi_set_drvdata(struct mipi_dbi_device *dev,
> +                                       void *data)
> +{
> +       dev_set_drvdata(&dev->dev, data);
> +}
> +
> +/* module_mipi_dbi_driver() - Helper macro for drivers that don't do
> + * anything special in module init/exit.  This eliminates a lot of
> + * boilerplate.  Each module may only use this macro once, and
> + * calling it replaces module_init() and module_exit()
> + */
> +#define module_mipi_dbi_driver(__mipi_dbi_driver) \
> +       module_driver(__mipi_dbi_driver, mipi_dbi_driver_register, \
> +                       mipi_dbi_driver_unregister)
> +
> +int mipi_dbi_set_data_width(struct mipi_dbi_device *dev, unsigned int width);
> +
> +int mipi_dbi_write_command(struct mipi_dbi_device *dev, u16 cmd);
> +int mipi_dbi_read_data(struct mipi_dbi_device *dev, u8 *data, size_t len);
> +int mipi_dbi_write_data(struct mipi_dbi_device *dev, const u8 *data,
> +                       size_t len);
> +
> +#endif /* __MIPI_DBI_BUS__ */
> --
> 1.8.1.5
>



-- 
Thanks and Regards
 Vikas Sajjan

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 08/19] video: display: Add MIPI DBI bus support
  2013-08-09 17:14 ` [PATCH/RFC v3 08/19] video: display: Add MIPI DBI bus support Laurent Pinchart
                     ` (2 preceding siblings ...)
  2013-09-04 10:50   ` Vikas Sajjan
@ 2013-09-04 12:52   ` Vikas Sajjan
  2013-09-06 14:56     ` Laurent Pinchart
  3 siblings, 1 reply; 83+ messages in thread
From: Vikas Sajjan @ 2013-09-04 12:52 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-fbdev, Sebastien Guiriec, DRI mailing list, Jesse Barnes,
	Benjamin Gaignard, Tom Gall, Kyungmin Park, Tomi Valkeinen,
	linux-media, Stephen Warren, Mark Zhang, Alexandre Courbot,
	Ragesh Radhakrishnan, Thomas Petazzoni, Sunil Joshi,
	Maxime Ripard, Marcus Lorentzon

 Hi Laurent,

On 9 August 2013 22:44, Laurent Pinchart
<laurent.pinchart+renesas@ideasonboard.com> wrote:
> MIPI DBI is a configurable-width parallel display bus that transmits
> commands and data.
>
> Add a new DBI Linux bus type that implements the usual bus
> infrastructure (including devices and drivers (un)registration and
> matching, and bus configuration and access functions).
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
>  drivers/video/display/Kconfig        |   8 ++
>  drivers/video/display/Makefile       |   1 +
>  drivers/video/display/mipi-dbi-bus.c | 234 +++++++++++++++++++++++++++++++++++
>  include/video/display.h              |   4 +
>  include/video/mipi-dbi-bus.h         | 125 +++++++++++++++++++
>  5 files changed, 372 insertions(+)
>  create mode 100644 drivers/video/display/mipi-dbi-bus.c
>  create mode 100644 include/video/mipi-dbi-bus.h
>
> diff --git a/drivers/video/display/Kconfig b/drivers/video/display/Kconfig
> index 1d533e7..f7532c1 100644
> --- a/drivers/video/display/Kconfig
> +++ b/drivers/video/display/Kconfig
> @@ -2,3 +2,11 @@ menuconfig DISPLAY_CORE
>         tristate "Display Core"
>         ---help---
>           Support common display framework for graphics devices.
> +
> +if DISPLAY_CORE
> +
> +config DISPLAY_MIPI_DBI
> +       tristate
> +       default n
> +
> +endif # DISPLAY_CORE
> diff --git a/drivers/video/display/Makefile b/drivers/video/display/Makefile
> index b907aad..59022d2 100644
> --- a/drivers/video/display/Makefile
> +++ b/drivers/video/display/Makefile
> @@ -1,3 +1,4 @@
>  display-y                                      := display-core.o \
>                                                    display-notifier.o
>  obj-$(CONFIG_DISPLAY_CORE)                     += display.o
> +obj-$(CONFIG_DISPLAY_MIPI_DBI)                 += mipi-dbi-bus.o
> diff --git a/drivers/video/display/mipi-dbi-bus.c b/drivers/video/display/mipi-dbi-bus.c
> new file mode 100644
> index 0000000..791fb4d
> --- /dev/null
> +++ b/drivers/video/display/mipi-dbi-bus.c
> @@ -0,0 +1,234 @@
> +/*
> + * MIPI DBI Bus
> + *
> + * Copyright (C) 2012 Renesas Solutions Corp.
> + *
> + * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> + *
> + * 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.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/export.h>
> +#include <linux/kernel.h>
> +#include <linux/list.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/pm.h>
> +#include <linux/pm_runtime.h>
> +
> +#include <video/mipi-dbi-bus.h>
> +
> +/* -----------------------------------------------------------------------------
> + * Bus operations
> + */
> +
> +int mipi_dbi_set_data_width(struct mipi_dbi_device *dev, unsigned int width)
> +{
> +       if (width != 8 && width != 16)
> +               return -EINVAL;
> +
> +       dev->data_width = width;
> +       return 0;
> +}
> +EXPORT_SYMBOL_GPL(mipi_dbi_set_data_width);
> +
> +int mipi_dbi_write_command(struct mipi_dbi_device *dev, u16 cmd)
> +{
> +       return dev->bus->ops->write_command(dev->bus, dev, cmd);


Can you help me in pointing out where these function pointer (
ops->write_command ) are assigned in case MIPI DBI.

In case of exynos  ( drivers/video/exynos/exynos_mipi_dsi.c ), we
assign them as below and register DSI as a platform device

 static struct mipi_dsim_master_ops master_ops = {
        .cmd_read                       = exynos_mipi_dsi_rd_data,
        .cmd_write                      = exynos_mipi_dsi_wr_data,
        .get_dsim_frame_done            = exynos_mipi_dsi_get_frame_done_status,
        .clear_dsim_frame_done          = exynos_mipi_dsi_clear_frame_done,
         .set_early_blank_mode           = exynos_mipi_dsi_early_blank_mode,
        .set_blank_mode                 = exynos_mipi_dsi_blank_mode,
};

Since now you are saying to have it as linux BUS, how should we
register these ops and how we can configure the MIPI DSI hw itself if
we register it as bus. I could not find any help in mipi-dbi-bus.c,
how we actually configure the MIPI DBI h/w itself.

ideally mipi-dbi-bus.c should have done 2 things
======================================

1. provide a framework to register the DBI kind of panel  = which is supported

2. provide a framework to register the actuall MIPI DBI H/W itself =
which i think is missing            ( correct me, if i am missing
anything )


> +}
> +EXPORT_SYMBOL_GPL(mipi_dbi_write_command);
> +
> +int mipi_dbi_write_data(struct mipi_dbi_device *dev, const u8 *data,
> +                       size_t len)
> +{
> +       return dev->bus->ops->write_data(dev->bus, dev, data, len);
> +}
> +EXPORT_SYMBOL_GPL(mipi_dbi_write_data);
> +
> +int mipi_dbi_read_data(struct mipi_dbi_device *dev, u8 *data, size_t len)
> +{
> +       return dev->bus->ops->read_data(dev->bus, dev, data, len);
> +}
> +EXPORT_SYMBOL_GPL(mipi_dbi_read_data);
> +
> +/* -----------------------------------------------------------------------------
> + * Bus type
> + */
> +
> +static const struct mipi_dbi_device_id *
> +mipi_dbi_match_id(const struct mipi_dbi_device_id *id,
> +                 struct mipi_dbi_device *dev)
> +{
> +       while (id->name[0]) {
> +               if (strcmp(dev->name, id->name) == 0) {
> +                       dev->id_entry = id;
> +                       return id;
> +               }
> +               id++;
> +       }
> +       return NULL;
> +}
> +
> +static int mipi_dbi_match(struct device *_dev, struct device_driver *_drv)
> +{
> +       struct mipi_dbi_device *dev = to_mipi_dbi_device(_dev);
> +       struct mipi_dbi_driver *drv = to_mipi_dbi_driver(_drv);
> +
> +       if (drv->id_table)
> +               return mipi_dbi_match_id(drv->id_table, dev) != NULL;
> +
> +       return (strcmp(dev->name, _drv->name) == 0);
> +}
> +
> +static ssize_t modalias_show(struct device *_dev, struct device_attribute *a,
> +                            char *buf)
> +{
> +       struct mipi_dbi_device *dev = to_mipi_dbi_device(_dev);
> +       int len = snprintf(buf, PAGE_SIZE, MIPI_DBI_MODULE_PREFIX "%s\n",
> +                          dev->name);
> +
> +       return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
> +}
> +
> +static struct device_attribute mipi_dbi_dev_attrs[] = {
> +       __ATTR_RO(modalias),
> +       __ATTR_NULL,
> +};
> +
> +static int mipi_dbi_uevent(struct device *_dev, struct kobj_uevent_env *env)
> +{
> +       struct mipi_dbi_device *dev = to_mipi_dbi_device(_dev);
> +
> +       add_uevent_var(env, "MODALIAS=%s%s", MIPI_DBI_MODULE_PREFIX,
> +                      dev->name);
> +       return 0;
> +}
> +
> +static const struct dev_pm_ops mipi_dbi_dev_pm_ops = {
> +       .runtime_suspend = pm_generic_runtime_suspend,
> +       .runtime_resume = pm_generic_runtime_resume,
> +       .suspend = pm_generic_suspend,
> +       .resume = pm_generic_resume,
> +       .freeze = pm_generic_freeze,
> +       .thaw = pm_generic_thaw,
> +       .poweroff = pm_generic_poweroff,
> +       .restore = pm_generic_restore,
> +};
> +
> +static struct bus_type mipi_dbi_bus_type = {
> +       .name           = "mipi-dbi",
> +       .dev_attrs      = mipi_dbi_dev_attrs,
> +       .match          = mipi_dbi_match,
> +       .uevent         = mipi_dbi_uevent,
> +       .pm             = &mipi_dbi_dev_pm_ops,
> +};
> +
> +/* -----------------------------------------------------------------------------
> + * Device and driver (un)registration
> + */
> +
> +/**
> + * mipi_dbi_device_register - register a DBI device
> + * @dev: DBI device we're registering
> + */
> +int mipi_dbi_device_register(struct mipi_dbi_device *dev,
> +                             struct mipi_dbi_bus *bus)
> +{
> +       device_initialize(&dev->dev);
> +
> +       dev->bus = bus;
> +       dev->dev.bus = &mipi_dbi_bus_type;
> +       dev->dev.parent = bus->dev;
> +
> +       if (dev->id != -1)
> +               dev_set_name(&dev->dev, "%s.%d", dev->name,  dev->id);
> +       else
> +               dev_set_name(&dev->dev, "%s", dev->name);
> +
> +       return device_add(&dev->dev);
> +}
> +EXPORT_SYMBOL_GPL(mipi_dbi_device_register);
> +
> +/**
> + * mipi_dbi_device_unregister - unregister a DBI device
> + * @dev: DBI device we're unregistering
> + */
> +void mipi_dbi_device_unregister(struct mipi_dbi_device *dev)
> +{
> +       device_del(&dev->dev);
> +       put_device(&dev->dev);
> +}
> +EXPORT_SYMBOL_GPL(mipi_dbi_device_unregister);
> +
> +static int mipi_dbi_drv_probe(struct device *_dev)
> +{
> +       struct mipi_dbi_driver *drv = to_mipi_dbi_driver(_dev->driver);
> +       struct mipi_dbi_device *dev = to_mipi_dbi_device(_dev);
> +
> +       return drv->probe(dev);
> +}
> +
> +static int mipi_dbi_drv_remove(struct device *_dev)
> +{
> +       struct mipi_dbi_driver *drv = to_mipi_dbi_driver(_dev->driver);
> +       struct mipi_dbi_device *dev = to_mipi_dbi_device(_dev);
> +       int ret;
> +
> +       ret = drv->remove(dev);
> +       if (ret < 0)
> +               return ret;
> +
> +       mipi_dbi_set_drvdata(dev, NULL);
> +
> +       return 0;
> +}
> +
> +/**
> + * mipi_dbi_driver_register - register a driver for DBI devices
> + * @drv: DBI driver structure
> + */
> +int mipi_dbi_driver_register(struct mipi_dbi_driver *drv)
> +{
> +       drv->driver.bus = &mipi_dbi_bus_type;
> +       if (drv->probe)
> +               drv->driver.probe = mipi_dbi_drv_probe;
> +       if (drv->remove)
> +               drv->driver.remove = mipi_dbi_drv_remove;
> +
> +       return driver_register(&drv->driver);
> +}
> +EXPORT_SYMBOL_GPL(mipi_dbi_driver_register);
> +
> +/**
> + * mipi_dbi_driver_unregister - unregister a driver for DBI devices
> + * @drv: DBI driver structure
> + */
> +void mipi_dbi_driver_unregister(struct mipi_dbi_driver *drv)
> +{
> +       driver_unregister(&drv->driver);
> +}
> +EXPORT_SYMBOL_GPL(mipi_dbi_driver_unregister);
> +
> +/* -----------------------------------------------------------------------------
> + * Init/exit
> + */
> +
> +static int __init mipi_dbi_init(void)
> +{
> +       return bus_register(&mipi_dbi_bus_type);
> +}
> +
> +static void __exit mipi_dbi_exit(void)
> +{
> +       bus_unregister(&mipi_dbi_bus_type);
> +}
> +
> +module_init(mipi_dbi_init);
> +module_exit(mipi_dbi_exit)
> +
> +MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
> +MODULE_DESCRIPTION("MIPI DBI Bus");
> +MODULE_LICENSE("GPL");
> diff --git a/include/video/display.h b/include/video/display.h
> index ba319d6..3138401 100644
> --- a/include/video/display.h
> +++ b/include/video/display.h
> @@ -17,6 +17,7 @@
>  #include <linux/list.h>
>  #include <linux/module.h>
>  #include <media/media-entity.h>
> +#include <video/mipi-dbi-bus.h>
>
>  #define DISPLAY_PIXEL_CODING(option, type, from, to, variant) \
>         (((option) << 17) | ((type) << 13) | ((variant) << 10) | \
> @@ -189,6 +190,9 @@ enum display_entity_interface_type {
>
>  struct display_entity_interface_params {
>         enum display_entity_interface_type type;
> +       union {
> +               struct mipi_dbi_interface_params dbi;
> +       } p;
>  };
>
>  struct display_entity_control_ops {
> diff --git a/include/video/mipi-dbi-bus.h b/include/video/mipi-dbi-bus.h
> new file mode 100644
> index 0000000..876b69d
> --- /dev/null
> +++ b/include/video/mipi-dbi-bus.h
> @@ -0,0 +1,125 @@
> +/*
> + * MIPI DBI Bus
> + *
> + * Copyright (C) 2012 Renesas Solutions Corp.
> + *
> + * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> + *
> + * 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.
> + */
> +
> +#ifndef __MIPI_DBI_BUS_H__
> +#define __MIPI_DBI_BUS_H__
> +
> +#include <linux/device.h>
> +
> +struct mipi_dbi_bus;
> +struct mipi_dbi_device;
> +
> +struct mipi_dbi_bus_ops {
> +       int (*write_command)(struct mipi_dbi_bus *bus,
> +                            struct mipi_dbi_device *dev, u16 cmd);
> +       int (*write_data)(struct mipi_dbi_bus *bus, struct mipi_dbi_device *dev,
> +                         const u8 *data, size_t len);
> +       int (*read_data)(struct mipi_dbi_bus *bus, struct mipi_dbi_device *dev,
> +                        u8 *data, size_t len);
> +};
> +
> +struct mipi_dbi_bus {
> +       struct device *dev;
> +       const struct mipi_dbi_bus_ops *ops;
> +};
> +
> +#define MIPI_DBI_MODULE_PREFIX         "mipi-dbi:"
> +#define MIPI_DBI_NAME_SIZE             32
> +
> +struct mipi_dbi_device_id {
> +       char name[MIPI_DBI_NAME_SIZE];
> +       __kernel_ulong_t driver_data    /* Data private to the driver */
> +                       __aligned(sizeof(__kernel_ulong_t));
> +};
> +
> +enum mipi_dbi_interface_type {
> +       MIPI_DBI_INTERFACE_TYPE_A,
> +       MIPI_DBI_INTERFACE_TYPE_B,
> +};
> +
> +#define MIPI_DBI_INTERFACE_TE          (1 << 0)
> +
> +struct mipi_dbi_interface_params {
> +       enum mipi_dbi_interface_type type;
> +       unsigned int flags;
> +
> +       unsigned int cs_setup;
> +       unsigned int rd_setup;
> +       unsigned int rd_latch;
> +       unsigned int rd_cycle;
> +       unsigned int rd_hold;
> +       unsigned int wr_setup;
> +       unsigned int wr_cycle;
> +       unsigned int wr_hold;
> +};
> +
> +#define MIPI_DBI_FLAG_ALIGN_LEFT       (1 << 0)
> +
> +struct mipi_dbi_device {
> +       const char *name;
> +       int id;
> +       struct device dev;
> +
> +       const struct mipi_dbi_device_id *id_entry;
> +       struct mipi_dbi_bus *bus;
> +
> +       unsigned int flags;
> +       unsigned int bus_width;
> +       unsigned int data_width;
> +};
> +
> +#define to_mipi_dbi_device(d)  container_of(d, struct mipi_dbi_device, dev)
> +
> +int mipi_dbi_device_register(struct mipi_dbi_device *dev,
> +                            struct mipi_dbi_bus *bus);
> +void mipi_dbi_device_unregister(struct mipi_dbi_device *dev);
> +
> +struct mipi_dbi_driver {
> +       int(*probe)(struct mipi_dbi_device *);
> +       int(*remove)(struct mipi_dbi_device *);
> +       struct device_driver driver;
> +       const struct mipi_dbi_device_id *id_table;
> +};
> +
> +#define to_mipi_dbi_driver(d)  container_of(d, struct mipi_dbi_driver, driver)
> +
> +int mipi_dbi_driver_register(struct mipi_dbi_driver *drv);
> +void mipi_dbi_driver_unregister(struct mipi_dbi_driver *drv);
> +
> +static inline void *mipi_dbi_get_drvdata(const struct mipi_dbi_device *dev)
> +{
> +       return dev_get_drvdata(&dev->dev);
> +}
> +
> +static inline void mipi_dbi_set_drvdata(struct mipi_dbi_device *dev,
> +                                       void *data)
> +{
> +       dev_set_drvdata(&dev->dev, data);
> +}
> +
> +/* module_mipi_dbi_driver() - Helper macro for drivers that don't do
> + * anything special in module init/exit.  This eliminates a lot of
> + * boilerplate.  Each module may only use this macro once, and
> + * calling it replaces module_init() and module_exit()
> + */
> +#define module_mipi_dbi_driver(__mipi_dbi_driver) \
> +       module_driver(__mipi_dbi_driver, mipi_dbi_driver_register, \
> +                       mipi_dbi_driver_unregister)
> +
> +int mipi_dbi_set_data_width(struct mipi_dbi_device *dev, unsigned int width);
> +
> +int mipi_dbi_write_command(struct mipi_dbi_device *dev, u16 cmd);
> +int mipi_dbi_read_data(struct mipi_dbi_device *dev, u8 *data, size_t len);
> +int mipi_dbi_write_data(struct mipi_dbi_device *dev, const u8 *data,
> +                       size_t len);
> +
> +#endif /* __MIPI_DBI_BUS__ */
> --
> 1.8.1.5
>



-- 
Thanks and Regards
 Vikas Sajjan

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 08/19] video: display: Add MIPI DBI bus support
  2013-08-26 11:10   ` Tomi Valkeinen
@ 2013-09-06 14:09     ` Laurent Pinchart
  2013-09-06 15:43       ` Tomi Valkeinen
  0 siblings, 1 reply; 83+ messages in thread
From: Laurent Pinchart @ 2013-09-06 14:09 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Laurent Pinchart, Tom Gall, Kyungmin Park, linux-media,
	Stephen Warren, Mark Zhang, Alexandre Courbot,
	Ragesh Radhakrishnan, Thomas Petazzoni, Sunil Joshi,
	Maxime Ripard, Vikas Sajjan, Marcus Lorentzon


[-- Attachment #1.1: Type: text/plain, Size: 2220 bytes --]

Hi Tomi,

On Monday 26 August 2013 14:10:50 Tomi Valkeinen wrote:
> On 09/08/13 20:14, Laurent Pinchart wrote:
> > MIPI DBI is a configurable-width parallel display bus that transmits
> > commands and data.
> > 
> > Add a new DBI Linux bus type that implements the usual bus
> > infrastructure (including devices and drivers (un)registration and
> > matching, and bus configuration and access functions).
> 
> This has been discussed before, but I don't remember that the issue would
> have been cleared, so I'm bringing it up again.
> 
> What benefit does a real Linux DBI (or DSI) bus give us, compared to
> representing the DBI the same way as DPI? DBI & DSI are in practice point-
> to-point buses, and they do not support probing. Is it just that because DBI
> and DSI can be used to control a device, they have to be Linux buses?

The idea was to reuse the Linux bus infrastructure to benefit from features 
such as power management. Implementing DBI/DSI control functions using a 
DBI/DSI bus is also pretty easy, and would allow controlling DBI/DSI entities 
much like we control I2C entities. I don't like the idea of using an I2C bus 
with I2C access functions on one side, and embedding the DBI/DSI access 
functions as part of CDF entity operations on the other side very much.

This being said, this isn't the part of CDF that matters the most to me (it's 
actually not part of CDF strictly speaking). If your model works well enough 
it won't be too hard to convince me :-)

> How do you see handling the devices where DBI or DSI is used for video only,
> and the control is handled via, say, i2c? The module has to register two
> drivers, and try to keep those in sync? I feel that could get rather hacky.

If DBI or DSI is used for video only you don't need DBI/DSI control 
operations, right ? So the entity driver will just be a regular I2C device 
driver.

> A real Linux bus would be necessary if we had devices that used DBI or DSI
> only for control, and some other video bus for video data. But that sounds
> so silly that I think we can just forget about the case.

I certainly hope so :-)

> Thus DBI and DSI are used either for video only, or video and control.

-- 
Regards,

Laurent Pinchart

[-- Attachment #1.2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 08/19] video: display: Add MIPI DBI bus support
  2013-09-04 10:50   ` Vikas Sajjan
@ 2013-09-06 14:37     ` Laurent Pinchart
  2013-09-18 10:59       ` Vikas Sajjan
  0 siblings, 1 reply; 83+ messages in thread
From: Laurent Pinchart @ 2013-09-06 14:37 UTC (permalink / raw)
  To: Vikas Sajjan
  Cc: linux-fbdev, Sebastien Guiriec, DRI mailing list, Jesse Barnes,
	Benjamin Gaignard, Laurent Pinchart, Tom Gall, Kyungmin Park,
	Tomi Valkeinen, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Marcus Lorentzon

Hi Vikas,

On Wednesday 04 September 2013 16:20:59 Vikas Sajjan wrote:
> On 9 August 2013 22:44, Laurent Pinchart wrote:
> > MIPI DBI is a configurable-width parallel display bus that transmits
> > commands and data.
> > 
> > Add a new DBI Linux bus type that implements the usual bus
> > infrastructure (including devices and drivers (un)registration and
> > matching, and bus configuration and access functions).
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> > 
> >  drivers/video/display/Kconfig        |   8 ++
> >  drivers/video/display/Makefile       |   1 + 
> >  drivers/video/display/mipi-dbi-bus.c | 234 ++++++++++++++++++++++++++++++
> >  include/video/display.h              |   4 +
> >  include/video/mipi-dbi-bus.h         | 125 +++++++++++++++++++
> >  5 files changed, 372 insertions(+)
> >  create mode 100644 drivers/video/display/mipi-dbi-bus.c
> >  create mode 100644 include/video/mipi-dbi-bus.h

[snip]

> > diff --git a/drivers/video/display/mipi-dbi-bus.c
> > b/drivers/video/display/mipi-dbi-bus.c new file mode 100644
> > index 0000000..791fb4d
> > --- /dev/null
> > +++ b/drivers/video/display/mipi-dbi-bus.c

[snip]

> > +/* ----------------------------------------------------------------------
> > + * Device and driver (un)registration
> > + */
> > +
> > +/**
> > + * mipi_dbi_device_register - register a DBI device
> > + * @dev: DBI device we're registering
> > + */
> > +int mipi_dbi_device_register(struct mipi_dbi_device *dev,
> > +                             struct mipi_dbi_bus *bus)
> > +{
> > +       device_initialize(&dev->dev);
> > +
> > +       dev->bus = bus;
> > +       dev->dev.bus = &mipi_dbi_bus_type;
> > +       dev->dev.parent = bus->dev;
> > +
> > +       if (dev->id != -1)
> > +               dev_set_name(&dev->dev, "%s.%d", dev->name,  dev->id);
> > +       else
> > +               dev_set_name(&dev->dev, "%s", dev->name);
> > +
> > +       return device_add(&dev->dev);
> > +}
> 
> The function looks very much specific to NON-DT case where you will be
> calling mipi_dbi_device_register() in the machine file.

You're absolutely right.

> I was actually trying to migrate to CDFv3 and adding MIPI DSI support
> for exynos5250,
> but in my case where exynos5250 is fully DT based, in which case we
> need something like ./drivers/of/platform.c for MIPI DBI and MIPI DSI
> to add the MIPI DBI/DSI device via DT way, ./drivers/of/mipi_dbi.c and
> ./drivers/of/mipi_dsi.c
> 
> may look like below,
> 
> int of_mipi_dbi_device_register(struct device_node *np,
>                                          const char *bus_id,
>                                          struct device *parent)
> {
>          struct mipi_dbi_device *dev;
>          dev = of_device_alloc(np, bus_id, parent);
>
>          if (!dev)
>                  return NULL;
>        device_initialize(dev);
> 
>        dev->bus = &mipi_dbi_bus_type;
>        dev->parent = parent;
> 
>        return of_device_add(dev);
> }
> 
> Correct me if I am wrong.

You're correct, but the implementation will need to be a little bit more 
complex than that. From an API point of view, something like 
of_i2c_register_devices() (drivers/of/of_i2c.c) would probably make sense. the 
function should iterate over child nodes, and call 
of_mipi_dbi_device_register() (we could maybe rename that to 
of_mipi_dbi_device_create() to mimic the platform device code) for each child.

In your above code, you should replace of_device_alloc() with 
of_mipi_dbi_device_alloc(), as of_device_alloc() allocates a struct 
platform_device. You should also call mipi_dsi_device_put() on the device if 
of_device_add() returns a failure.

Would you like to send a patch on top of 08/19 to implement this ?

> > +EXPORT_SYMBOL_GPL(mipi_dbi_device_register);
> > +
> > +/**
> > + * mipi_dbi_device_unregister - unregister a DBI device
> > + * @dev: DBI device we're unregistering
> > + */
> > +void mipi_dbi_device_unregister(struct mipi_dbi_device *dev)
> > +{
> > +       device_del(&dev->dev);
> > +       put_device(&dev->dev);
> > +}
> > +EXPORT_SYMBOL_GPL(mipi_dbi_device_unregister);
> > +
> > +static int mipi_dbi_drv_probe(struct device *_dev)
> > +{
> > +       struct mipi_dbi_driver *drv = to_mipi_dbi_driver(_dev->driver);
> > +       struct mipi_dbi_device *dev = to_mipi_dbi_device(_dev);
> 
> Here we are assuming that  mipi_dbi_device can be obtained by using
> _dev pointer, which may NOT be true in DT case, i think.

Why wouldn't it be true (if we create the devices as explained above) ?

> let me know if i am missing something.
> 
> if you can give me a example for DT case, that would be helpful.

I'm afraid I don't have any, as the DBI drivers I wrote are used by a platform 
that doesn't support DT.

> > +
> > +       return drv->probe(dev);
> > +}

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 08/19] video: display: Add MIPI DBI bus support
  2013-09-04 12:52   ` Vikas Sajjan
@ 2013-09-06 14:56     ` Laurent Pinchart
  0 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2013-09-06 14:56 UTC (permalink / raw)
  To: Vikas Sajjan
  Cc: linux-fbdev, Sebastien Guiriec, DRI mailing list, Jesse Barnes,
	Benjamin Gaignard, Laurent Pinchart, Tom Gall, Kyungmin Park,
	Tomi Valkeinen, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Marcus Lorentzon

Hi Vikas,

On Wednesday 04 September 2013 18:22:45 Vikas Sajjan wrote:
> On 9 August 2013 22:44, Laurent Pinchart wrote:
> > MIPI DBI is a configurable-width parallel display bus that transmits
> > commands and data.
> > 
> > Add a new DBI Linux bus type that implements the usual bus
> > infrastructure (including devices and drivers (un)registration and
> > matching, and bus configuration and access functions).
> > 
> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> > ---
> > 
> >  drivers/video/display/Kconfig        |   8 ++
> >  drivers/video/display/Makefile       |   1 +
> >  drivers/video/display/mipi-dbi-bus.c | 234 ++++++++++++++++++++++++++++++
> >  include/video/display.h              |   4 +
> >  include/video/mipi-dbi-bus.h         | 125 +++++++++++++++++++
> >  5 files changed, 372 insertions(+)
> >  create mode 100644 drivers/video/display/mipi-dbi-bus.c
> >  create mode 100644 include/video/mipi-dbi-bus.h

[snip]

> > diff --git a/drivers/video/display/mipi-dbi-bus.c
> > b/drivers/video/display/mipi-dbi-bus.c new file mode 100644
> > index 0000000..791fb4d
> > --- /dev/null
> > +++ b/drivers/video/display/mipi-dbi-bus.c

[snip]

> > +/* ----------------------------------------------------------------------
> > + * Bus operations
> > + */
> > +
> > +int mipi_dbi_set_data_width(struct mipi_dbi_device *dev, unsigned int
> > width)
> > +{
> > +       if (width != 8 && width != 16)
> > +               return -EINVAL;
> > +
> > +       dev->data_width = width;
> > +       return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(mipi_dbi_set_data_width);
> > +
> > +int mipi_dbi_write_command(struct mipi_dbi_device *dev, u16 cmd)
> > +{
> > +       return dev->bus->ops->write_command(dev->bus, dev, cmd);
> 
> Can you help me in pointing out where these function pointer
> (ops->write_command) are assigned in case MIPI DBI.
> 
> In case of exynos (drivers/video/exynos/exynos_mipi_dsi.c), we
> assign them as below and register DSI as a platform device
> 
>  static struct mipi_dsim_master_ops master_ops = {
>         .cmd_read                       = exynos_mipi_dsi_rd_data,
>         .cmd_write                      = exynos_mipi_dsi_wr_data,
>         .get_dsim_frame_done            =
> exynos_mipi_dsi_get_frame_done_status,
>         .clear_dsim_frame_done          = exynos_mipi_dsi_clear_frame_done,
>         .set_early_blank_mode           = exynos_mipi_dsi_early_blank_mode,
>         .set_blank_mode                 = exynos_mipi_dsi_blank_mode, };
> 
> Since now you are saying to have it as linux BUS, how should we
> register these ops and how we can configure the MIPI DSI hw itself if
> we register it as bus. I could not find any help in mipi-dbi-bus.c,
> how we actually configure the MIPI DBI h/w itself.
> 
> ideally mipi-dbi-bus.c should have done 2 things
> ======================================
> 
> 1. provide a framework to register the DBI kind of panel  = which is
> supported
> 
> 2. provide a framework to register the actuall MIPI DBI H/W itself =
> which i think is missing (correct me, if i am missing anything)

Indeed, you're right... I'll go hide in a dark corner now.

Thinking about it, I should instead implement the missing code, that would 
more helpful.

The patch is missing MIPI DBI bus registration. If you have already written 
bus registration code feel free to send a patch, otherwise I'll fix it (I'll 
wait for your confirmation first).

> > +}

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 08/19] video: display: Add MIPI DBI bus support
  2013-09-06 14:09     ` Laurent Pinchart
@ 2013-09-06 15:43       ` Tomi Valkeinen
  2013-09-07  9:35         ` Tomi Valkeinen
  0 siblings, 1 reply; 83+ messages in thread
From: Tomi Valkeinen @ 2013-09-06 15:43 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Laurent Pinchart, Tom Gall, Kyungmin Park, linux-media,
	Stephen Warren, Mark Zhang, Alexandre Courbot,
	Ragesh Radhakrishnan, Thomas Petazzoni, Sunil Joshi,
	Maxime Ripard, Vikas Sajjan, Marcus Lorentzon


[-- Attachment #1.1: Type: text/plain, Size: 3450 bytes --]

On 06/09/13 17:09, Laurent Pinchart wrote:
> Hi Tomi,
> 
> On Monday 26 August 2013 14:10:50 Tomi Valkeinen wrote:
>> On 09/08/13 20:14, Laurent Pinchart wrote:
>>> MIPI DBI is a configurable-width parallel display bus that transmits
>>> commands and data.
>>>
>>> Add a new DBI Linux bus type that implements the usual bus
>>> infrastructure (including devices and drivers (un)registration and
>>> matching, and bus configuration and access functions).
>>
>> This has been discussed before, but I don't remember that the issue would
>> have been cleared, so I'm bringing it up again.
>>
>> What benefit does a real Linux DBI (or DSI) bus give us, compared to
>> representing the DBI the same way as DPI? DBI & DSI are in practice point-
>> to-point buses, and they do not support probing. Is it just that because DBI
>> and DSI can be used to control a device, they have to be Linux buses?
> 
> The idea was to reuse the Linux bus infrastructure to benefit from features 
> such as power management. Implementing DBI/DSI control functions using a 
> DBI/DSI bus is also pretty easy, and would allow controlling DBI/DSI entities 
> much like we control I2C entities. I don't like the idea of using an I2C bus 
> with I2C access functions on one side, and embedding the DBI/DSI access 
> functions as part of CDF entity operations on the other side very much.

While I somewhat like the thought of having DBI and DSI as Linux buses,
I just don't see how it would work. Well, I'm mostly thinking about DSI
here, I have not used DBI for years.

Also, I might remember wrong, but I think I saw Linus expressing his
opinion at some point that he doesn't really like the idea of having a
Linux bus for simple point-to-point buses, which don't have probing
support, and so there isn't much "bus" to speak of, just a point to
point link.

And I think we get the same power management with just having a device
as a child device of another.

> This being said, this isn't the part of CDF that matters the most to me (it's 
> actually not part of CDF strictly speaking). If your model works well enough 
> it won't be too hard to convince me :-)
> 
>> How do you see handling the devices where DBI or DSI is used for video only,
>> and the control is handled via, say, i2c? The module has to register two
>> drivers, and try to keep those in sync? I feel that could get rather hacky.
> 
> If DBI or DSI is used for video only you don't need DBI/DSI control 
> operations, right ? So the entity driver will just be a regular I2C device 
> driver.

Well, DSI can't be used just like that. You need to configure it.

The thing is, DSI is used for both control and video. They are really
the same thing, both are sent as DSI packets. Both need similar kind of
configuration for the bus. If the DSI peripheral sits on a DSI bus, I
imagine this configuration is done via the DSI bus support. But if
there's no DSI bus, how is the configuration done?

I guess a possibility is to have a fixed configuration that cannot be
changed dynamically. But I have a feeling that it'll be a bit limiting
for some cases.

And even with fixed configuration, I think the configuration would
somehow be passed as DSI bus parameters from the board files or in the
DT data (the same way as, say i2c bus speed). If there's no DSI bus, as
the DSI peripheral sits on the i2c bus, where are the parameters?

 Tomi



[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
  2013-08-21 12:22         ` Rob Clark
@ 2013-09-06 16:16           ` Laurent Pinchart
  2013-09-09 12:12           ` Tomi Valkeinen
  1 sibling, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2013-09-06 16:16 UTC (permalink / raw)
  To: Rob Clark
  Cc: Linux Fbdev development list, Benjamin Gaignard, dri-devel,
	Jesse Barnes, Sebastien Guiriec, Laurent Pinchart, Tom Gall,
	Ragesh Radhakrishnan, Tomi Valkeinen, linux-media,
	Stephen Warren, Mark Zhang, Alexandre Courbot, Thomas Petazzoni,
	Sunil Joshi, Kyungmin Park, Maxime Ripard, Vikas Sajjan,
	Marcus Lorentzon

Hi Rob and Sascha,

On Wednesday 21 August 2013 08:22:59 Rob Clark wrote:
> On Wed, Aug 21, 2013 at 3:09 AM, Sascha Hauer wrote:
> > On Tue, Aug 20, 2013 at 02:40:55PM -0400, Rob Clark wrote:
> >> On Tue, Aug 20, 2013 at 11:24 AM, Laurent Pinchart wrote:
> >> > Hi Rob,
> >> > 
> >> >> Or maybe, put another way, I still think we should still optimize for
> >> >> the common case. I mean I'm sure you *can* design hw that has an
> >> >> LVDS->DP bridge in the capture path, and if you had something like an
> >> >> FPGA where that was cheap to do maybe you even would (for fun). But if
> >> >> in the real world, there are only one or two cases of actual hw using
> >> >> the same bridge in a capture pipeline which is normally used in
> >> >> display pipelines, then duplicating some small bit of code for that
> >> >> abnormal case if it makes things easier for the common case, seems
> >> >> like a reasonable trade-off to me.
> >> > 
> >> > That was my opinion as well until I started working on a Xilinx
> >> > platform. There's dozens of IP cores there that are used in both
> >> > capture and display pipelines.
> >> 
> >> or maybe just some helper lib's to handling the register level
> >> programming?

Many chips and IP cores in KMS and V4L2 pipelines are pretty simple, and the 
bulk of the driver is just an API implementation. Register poking is usually a 
small percentage of the code (that's of course not the case for the more 
complex IP cores, but those are usually not shared).

> >> Anyways, I guess you can call it a "worse is better" thing, but if you
> >> can get 90% of the desired effect for 10% of the work, take the
> >> simpler solution.  I don't think we should make things more layered or
> >> more difficult for one exceptional case.

The point is I believe they will become less and less exceptional over time. 
One might argue that CDF is a revolutionary approach as opposed to an 
evolutionary approach, but looking at the future I believe we'll need a much 
bigger disruption if we wait too long.

> >> > Furthermore, FPGA display pipelines being made of individual IP cores,
> >> > we need a way to write one driver per IP core and make them all
> >> > interact. The recently proposed drm_bridge is one possible solution to
> >> > this issue (and to a different but similar issue that trigerred the
> >> > development of drm_bridge), but it's in my opinion not generic enough.
> >> > We're facing several problems that are related, it would really be a
> >> > shame not to solve them with a good enough framework.>> 
> >>
> >> well, I've been working on DSI panel support in msm drm, and also been
> >> looking at the patches to add DSI support in i915.  And the panel
> >> interface ends up looking basically like the drm_bridge interface.
> >> Perhaps the only thing not generic there is the name.

Don't get me wrong, drm_bridge is an interesting idea, but I think it's a bit 
limited.

> >> >> I mean, take a DSI panel driver, for example.. anything but a trivial
> >> >> panel driver, you are going to want to expose some custom properties
> >> >> on the connector for controlling non-standard features. So you end up
> >> >> with both cdf_foo for the common part, and drm_foo for gluing in the
> >> >> properties. And now these two parts which otherwise would be one, end
> >> >> up having to stay in sync merged through different trees, etc. It
> >> >> seems a lot like making my life more difficult for a fairly
> >> >> hypothetical gain ;-)
> >> > 
> >> > The DSI panel driver should not be split into two parts. It should
> >> > implement a CDF entity, any glue needed for DRM will not be part of
> >> > the panel driver.
> >>
> >> right, but that glue ends up needing to be *somewhere*, which makes it
> >> the 2nd part.
> >> 
> >> >> Or, take an hdmi or DP bridge. To use any of the common
> >> >> infrastructure/helpers in drm, you end up implementing a generic
> >> >> interface, where both the producer and consumer is inside drm. Which
> >> >> just seems a bit pointless and extra hoops to jump through. Especially
> >> >> when we discover that we need to extend/enhance the common interface
> >> >> outside of drm to make it work. (I'm thinking of
> >> >> display_entity_control_ops::get_modes() here, but I'm sure there are
> >> >> more examples.) And I think we'll run into similar issues with
> >> >> display_entity_control_ops::set_state(), since the on<->off sequencing
> >> >> can get hairy when the upstream/downstream entity is fed a clk by the
> >> >> downstream/upstream entity. And similarly, I think we'll go through a
> >> >> few revisions of DSI panel/bus params before we have everything that
> >> >> everyone needs.
> >> > 
> >> > I don't see where needing multiple revisions of a patch set would be
> >> > bad :-)
> >>
> >> I mean over multiple kernel revisions, as people start adding support
> >> for new hw and run into limitations of the "framework".
> > 
> > A framework can be changed, extended and fixed. In the end we talking
> > about a completely in-kernel framework for which we do not have to
> > maintain a stable API.
> 
> oh sure, this is why I'd be absolutely against exposing this to userspace
> currently..

At least we agree on that, good :-)

> But my only point here was that an in-drm framework, all the fix-ups due to
> a framework change are sorted out before Dave sends his pull req to linus. 
> We do this on a semi-regular basis already in drm already.

I understand. But DRM drivers already depend on lots of infrastructure code 
that is not part of DRM (you could of course argue that it's not a valid 
reason to add one more :-)).

> Anyways, not a show-stopper thing.. just (in my mind) one additional
> inconvenience (and not really the biggest one) about having the "framework"
> outside of drm.  I'm more concerned about just having the "display entity"
> code at a layer below the helpers and property api's that I'd like to use in
> drm.

I very much like the KMS property API (there's of course always room for 
improvements), we're actually thinking about a property API for V4L2 as well. 
My concern is that we need something shareable between subsystems, and the KMS 
version is a bit too tied to DRM/KMS for that purpose. For instance struct 
drm_property inherits struct drm_mode_object, and thus requires a DRM device 
to allocate IDs. This is the kind of really low-level issues that we will need 
to sort out one way or the other. If we can't require a V4L2 driver to 
implement a drm_device, or the other around (and I believe it would be 
unreasonable to do so), we will need a neutral middle-ground.

> And just to be clear, part of my negative experience about this is the
> omapdss/omapdrm split.  I just see cfd outside of drm as encouraging
> others to make the same mistake.

I absolutely agree that we should not repeat that mistake. We hopefully have a 
bit more experience now, and we should catch this kind of issue during code 
review in the worst case.

> >> We've already figured out that just having enable() and disable() is
> >> not sufficient for displayport link training.  I'm not sure what else
> >> we'll discover.
> > 
> > It's pretty much expected that other things will be discovered, but this
> > will also happen with all sub-drm-driver frameworks we currently have.
> 
> right, which is why I want to "optimize" for this case by having everything
> effected by evolving the framework merged via drm.
> 
> >> I'm not saying not to solve (most of these) problems.. I don't think
> >> chaining multiple drm_bridge's is impossible, I can think of at least
> >> two ways to implement it.  But I think we should solve that as someone
> >> is adding support for hw that uses this.  This (a) lets us break
> >> things up into smaller more incremental changes (drm_bridge is
> >> *considerably* smaller than the current CDF patchset), and (b) avoids
> >> us solving the wrong problems.
> >> 
> >> btw, I think DT bindings is orthogonal to this discussion.
> > 
> > Not really. The common display framework is about splitting the pipeline
> > into its components and adding a common view to the components. It's CDF
> > helper code that can translate a DT binding directly into a encoder
> > pipeline.
> 
> yes, DT binding are orthogonal.  This is something that should work
> for BIOS, ACPI, DT, fex (just kidding),

:-D

> etc.  I mean there might be some DT helpers, but that should be kind of on
> the side.
>
> If DT binding are really to be OS independent, we probably need some better
> way to deal w/ collecting up DT nodes for one (userspace visible) driver (or
> cases where driver <-> DT is not 1<->1).  But that is really an entirely
> different topic, or at least not applicable to where the "framework" lives.

I pretty much agree, DT bindings won't depend on whether we upstream the code 
to drivers/video/, drivers/gpu/ or drivers/media/. However, it's easy to 
design DT bindings with a particular framework implementation in mind and use 
shortcuts that make the bindings difficult to use should a different framework 
be implemented. We need to be careful about this. On the upside we now have 
more experienced DT bindings reviewers than a couple of years ago, I'm thus 
pretty optimistic.

-- 
Regards,

Laurent Pinchart

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 08/19] video: display: Add MIPI DBI bus support
  2013-09-06 15:43       ` Tomi Valkeinen
@ 2013-09-07  9:35         ` Tomi Valkeinen
  0 siblings, 0 replies; 83+ messages in thread
From: Tomi Valkeinen @ 2013-09-07  9:35 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Laurent Pinchart, Tom Gall, Kyungmin Park, linux-media,
	Stephen Warren, Mark Zhang, Alexandre Courbot,
	Ragesh Radhakrishnan, Thomas Petazzoni, Sunil Joshi,
	Maxime Ripard, Vikas Sajjan, Marcus Lorentzon


[-- Attachment #1.1: Type: text/plain, Size: 5117 bytes --]

On 06/09/13 18:43, Tomi Valkeinen wrote:
> On 06/09/13 17:09, Laurent Pinchart wrote:
>> Hi Tomi,
>>
>> On Monday 26 August 2013 14:10:50 Tomi Valkeinen wrote:
>>> On 09/08/13 20:14, Laurent Pinchart wrote:
>>>> MIPI DBI is a configurable-width parallel display bus that transmits
>>>> commands and data.
>>>>
>>>> Add a new DBI Linux bus type that implements the usual bus
>>>> infrastructure (including devices and drivers (un)registration and
>>>> matching, and bus configuration and access functions).
>>>
>>> This has been discussed before, but I don't remember that the issue would
>>> have been cleared, so I'm bringing it up again.
>>>
>>> What benefit does a real Linux DBI (or DSI) bus give us, compared to
>>> representing the DBI the same way as DPI? DBI & DSI are in practice point-
>>> to-point buses, and they do not support probing. Is it just that because DBI
>>> and DSI can be used to control a device, they have to be Linux buses?
>>
>> The idea was to reuse the Linux bus infrastructure to benefit from features 
>> such as power management. Implementing DBI/DSI control functions using a 
>> DBI/DSI bus is also pretty easy, and would allow controlling DBI/DSI entities 
>> much like we control I2C entities. I don't like the idea of using an I2C bus 
>> with I2C access functions on one side, and embedding the DBI/DSI access 
>> functions as part of CDF entity operations on the other side very much.
> 
> While I somewhat like the thought of having DBI and DSI as Linux buses,
> I just don't see how it would work. Well, I'm mostly thinking about DSI
> here, I have not used DBI for years.
> 
> Also, I might remember wrong, but I think I saw Linus expressing his
> opinion at some point that he doesn't really like the idea of having a
> Linux bus for simple point-to-point buses, which don't have probing
> support, and so there isn't much "bus" to speak of, just a point to
> point link.
> 
> And I think we get the same power management with just having a device
> as a child device of another.
> 
>> This being said, this isn't the part of CDF that matters the most to me (it's 
>> actually not part of CDF strictly speaking). If your model works well enough 
>> it won't be too hard to convince me :-)
>>
>>> How do you see handling the devices where DBI or DSI is used for video only,
>>> and the control is handled via, say, i2c? The module has to register two
>>> drivers, and try to keep those in sync? I feel that could get rather hacky.
>>
>> If DBI or DSI is used for video only you don't need DBI/DSI control 
>> operations, right ? So the entity driver will just be a regular I2C device 
>> driver.
> 
> Well, DSI can't be used just like that. You need to configure it.
> 
> The thing is, DSI is used for both control and video. They are really
> the same thing, both are sent as DSI packets. Both need similar kind of
> configuration for the bus. If the DSI peripheral sits on a DSI bus, I
> imagine this configuration is done via the DSI bus support. But if
> there's no DSI bus, how is the configuration done?
> 
> I guess a possibility is to have a fixed configuration that cannot be
> changed dynamically. But I have a feeling that it'll be a bit limiting
> for some cases.
> 
> And even with fixed configuration, I think the configuration would
> somehow be passed as DSI bus parameters from the board files or in the
> DT data (the same way as, say i2c bus speed). If there's no DSI bus, as
> the DSI peripheral sits on the i2c bus, where are the parameters?

Continuing my thoughts on the bus issue, I think there's a fundamental
difference between "real" buses like i2c and DSI/DBI: i2c peripherals
are designed with the mind set that there are other peripherals on the
bus, whereas DSI/DBI peripherals are known to be alone, and the DSI/DBI
peripheral may thus require the bus parameters to be changed according
to the whims of the peripheral.

Some examples coming to my mind from the hardware I know are the need to
change the DBI bus width depending on what is being sent, changing the
DSI bus clock speed, changing DSI return packet size.

It's ok for the DBI/DSI peripheral HW designers to require things like
that, because the spec doesn't say those can't be done, and the
peripheral is alone on the bus.

We can support those kinds of operations both with the bus model you
have, and my no-bus model. But with your bus model, I believe at least
some of those operations may be needed even when the peripheral is
controlled via i2c/spi.

This also is related to the control model. I'm not sure of the details
of the pipeline controller, but I fear that having the controller be the
entity that knows about the strange needs of individual video
peripherals will lead to lots of customized controllers for individual
boards.

That said, I agree that it's difficult to embed all the information into
individual device drivers (although that's where it should be), because
sometimes a wider view of the pipeline is needed to properly configure
things.

 Tomi



[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
  2013-08-21 12:22         ` Rob Clark
  2013-09-06 16:16           ` Laurent Pinchart
@ 2013-09-09 12:12           ` Tomi Valkeinen
  2013-09-09 14:17             ` Rob Clark
  1 sibling, 1 reply; 83+ messages in thread
From: Tomi Valkeinen @ 2013-09-09 12:12 UTC (permalink / raw)
  To: Rob Clark
  Cc: Linux Fbdev development list, dri-devel, Jesse Barnes,
	Laurent Pinchart, Benjamin Gaignard, Laurent Pinchart, Tom Gall,
	Ragesh Radhakrishnan, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Thomas Petazzoni, Sunil Joshi, Kyungmin Park,
	Maxime Ripard, Vikas Sajjan, Marcus Lorentzon


[-- Attachment #1.1: Type: text/plain, Size: 667 bytes --]

On 21/08/13 15:22, Rob Clark wrote:

> And just to be clear, part of my negative experience about this is the
> omapdss/omapdrm split.  I just see cfd outside of drm as encouraging
> others to make the same mistake.

Feel free to disagree, but I think the omapdss/omapdrm split is a bit
different matter. The main problem there was splitting the control of a
single device (OMAP DSS, and more specifically, DISPC) into two.

I don't see CDF causing anything similar. A single DRM driver should
manage the DISPC in OMAP's case, and it should (probably) also control
the external encoders and panel, even if those are independent CDF drivers.

 Tomi



[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
  2013-09-09 12:12           ` Tomi Valkeinen
@ 2013-09-09 14:17             ` Rob Clark
  2013-09-09 14:58               ` Tomi Valkeinen
  0 siblings, 1 reply; 83+ messages in thread
From: Rob Clark @ 2013-09-09 14:17 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Linux Fbdev development list, dri-devel, Jesse Barnes,
	Laurent Pinchart, Benjamin Gaignard, Laurent Pinchart, Tom Gall,
	Ragesh Radhakrishnan, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Thomas Petazzoni, Sunil Joshi, Kyungmin Park,
	Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

On Mon, Sep 9, 2013 at 8:12 AM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote:
> On 21/08/13 15:22, Rob Clark wrote:
>
>> And just to be clear, part of my negative experience about this is the
>> omapdss/omapdrm split.  I just see cfd outside of drm as encouraging
>> others to make the same mistake.
>
> Feel free to disagree, but I think the omapdss/omapdrm split is a bit
> different matter. The main problem there was splitting the control of a
> single device (OMAP DSS, and more specifically, DISPC) into two.

I don't completely care about the *device* split (we have drm drivers
that are multiple devices), as much as the directory and code layout
split.

We have helper code for edid probing, DP, etc in drm.  Drivers should
be using this to avoid duplicating code unnecessarily.  But that gets
difficult when the drivers are outside of drm.  (That is the best case
scenario, assuming we avoid any impedance mismatch between CDF and
KMS, that we come up with a way to share property code, etc.)

I don't see any way that putting it outside of drm/kms makes anything
any easier.. and I see plenty of potential for making things harder.
I have enough other work to do, hence I vote for 'easier' ;-)

That all said, I don't think CDF really changes anything from the
perspective of needing drm_bridge, drm_panel, etc.  I suppose they can
co-exist, possibly in some cases drm/kms objects are just wrappers for
CDF objects.  But if I do see new driver code that is duplicating what
can be done w/ helpers in drm (see drivers/video/exynos/*dp*), or with
unnecessary complexity, I would nak it.. just the same as I would do
with new drivers in drm which aren't using the appropriate helpers,
etc.

BR,
-R


> I don't see CDF causing anything similar. A single DRM driver should
> manage the DISPC in OMAP's case, and it should (probably) also control
> the external encoders and panel, even if those are independent CDF drivers.
>
>  Tomi
>
>

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
  2013-09-09 14:17             ` Rob Clark
@ 2013-09-09 14:58               ` Tomi Valkeinen
  2013-09-09 15:10                 ` Rob Clark
  0 siblings, 1 reply; 83+ messages in thread
From: Tomi Valkeinen @ 2013-09-09 14:58 UTC (permalink / raw)
  To: Rob Clark
  Cc: Linux Fbdev development list, dri-devel, Jesse Barnes,
	Laurent Pinchart, Benjamin Gaignard, Laurent Pinchart, Tom Gall,
	Ragesh Radhakrishnan, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Thomas Petazzoni, Sunil Joshi, Kyungmin Park,
	Maxime Ripard, Vikas Sajjan, Marcus Lorentzon


[-- Attachment #1.1: Type: text/plain, Size: 1729 bytes --]

On 09/09/13 17:17, Rob Clark wrote:
> On Mon, Sep 9, 2013 at 8:12 AM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote:
>> On 21/08/13 15:22, Rob Clark wrote:
>>
>>> And just to be clear, part of my negative experience about this is the
>>> omapdss/omapdrm split.  I just see cfd outside of drm as encouraging
>>> others to make the same mistake.
>>
>> Feel free to disagree, but I think the omapdss/omapdrm split is a bit
>> different matter. The main problem there was splitting the control of a
>> single device (OMAP DSS, and more specifically, DISPC) into two.
> 
> I don't completely care about the *device* split (we have drm drivers
> that are multiple devices), as much as the directory and code layout
> split.
> 
> We have helper code for edid probing, DP, etc in drm.  Drivers should
> be using this to avoid duplicating code unnecessarily.  But that gets
> difficult when the drivers are outside of drm.  (That is the best case
> scenario, assuming we avoid any impedance mismatch between CDF and
> KMS, that we come up with a way to share property code, etc.)

Ok, I thought you were referring to the apply etc. stuff we spent lots
of time solving for omapdss/omapdrm. That all was caused by the split we
have for the control for DISPC.

I, on the other hand, don't so much care about duplicating code. Sure, I
always try to avoid it. But if I need a helper in non-DRM context that
does the same thing as a helper DRM already has, I don't see any issue
in implementing it.

In fact, I'd prefer at least some of the helpers DRM has (say, videomode
related and EDID parsing) to be moved out from DRM. There's no reason to
tie them to DRM. That would avoid code duplication.

 Tomi



[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
  2013-09-09 14:58               ` Tomi Valkeinen
@ 2013-09-09 15:10                 ` Rob Clark
  0 siblings, 0 replies; 83+ messages in thread
From: Rob Clark @ 2013-09-09 15:10 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Linux Fbdev development list, dri-devel, Jesse Barnes,
	Laurent Pinchart, Benjamin Gaignard, Laurent Pinchart, Tom Gall,
	Ragesh Radhakrishnan, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Thomas Petazzoni, Sunil Joshi, Kyungmin Park,
	Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

On Mon, Sep 9, 2013 at 10:58 AM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote:
> On 09/09/13 17:17, Rob Clark wrote:
>> On Mon, Sep 9, 2013 at 8:12 AM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote:
>>> On 21/08/13 15:22, Rob Clark wrote:
>>>
>>>> And just to be clear, part of my negative experience about this is the
>>>> omapdss/omapdrm split.  I just see cfd outside of drm as encouraging
>>>> others to make the same mistake.
>>>
>>> Feel free to disagree, but I think the omapdss/omapdrm split is a bit
>>> different matter. The main problem there was splitting the control of a
>>> single device (OMAP DSS, and more specifically, DISPC) into two.
>>
>> I don't completely care about the *device* split (we have drm drivers
>> that are multiple devices), as much as the directory and code layout
>> split.
>>
>> We have helper code for edid probing, DP, etc in drm.  Drivers should
>> be using this to avoid duplicating code unnecessarily.  But that gets
>> difficult when the drivers are outside of drm.  (That is the best case
>> scenario, assuming we avoid any impedance mismatch between CDF and
>> KMS, that we come up with a way to share property code, etc.)
>
> Ok, I thought you were referring to the apply etc. stuff we spent lots
> of time solving for omapdss/omapdrm. That all was caused by the split we
> have for the control for DISPC.

yeah, I wasn't particularly referring to that (although it would have
been quicker to fix if it was all in drm)

> I, on the other hand, don't so much care about duplicating code. Sure, I
> always try to avoid it. But if I need a helper in non-DRM context that
> does the same thing as a helper DRM already has, I don't see any issue
> in implementing it.
>
> In fact, I'd prefer at least some of the helpers DRM has (say, videomode
> related and EDID parsing) to be moved out from DRM. There's no reason to
> tie them to DRM. That would avoid code duplication.

If there are easy / non-intrusive ways to make helpers more generic, I
don't mind.  But for better or for worse, drm/kms is the modern
display framework for the kernel, so moving helpers outside of drm
isn't something I'm going to go out of my way to do.  And, speaking
with my distro-hat on, dependencies outside of drm make my work harder
to backport new hw support of bugfixes to long-term supported distro
kernels..  but that doesn't stop us, when there is good reason to do
so (see ww_mutex, for example), but it doesn't make me super excited
about increasing dependencies outside of drm when there is no good
reason.  I suppose the folks porting drm/kms drivers to *BSD probably
feel the same way.

BR,
-R

>  Tomi
>
>

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 08/19] video: display: Add MIPI DBI bus support
  2013-09-06 14:37     ` Laurent Pinchart
@ 2013-09-18 10:59       ` Vikas Sajjan
  0 siblings, 0 replies; 83+ messages in thread
From: Vikas Sajjan @ 2013-09-18 10:59 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-fbdev, Sebastien Guiriec, DRI mailing list, Jesse Barnes,
	Benjamin Gaignard, Laurent Pinchart, Tom Gall, Kyungmin Park,
	Tomi Valkeinen, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Marcus Lorentzon

Hi Laurent,

On 6 September 2013 20:07, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> Hi Vikas,
>
> On Wednesday 04 September 2013 16:20:59 Vikas Sajjan wrote:
>> On 9 August 2013 22:44, Laurent Pinchart wrote:
>> > MIPI DBI is a configurable-width parallel display bus that transmits
>> > commands and data.
>> >
>> > Add a new DBI Linux bus type that implements the usual bus
>> > infrastructure (including devices and drivers (un)registration and
>> > matching, and bus configuration and access functions).
>> >
>> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>> > ---
>> >
>> >  drivers/video/display/Kconfig        |   8 ++
>> >  drivers/video/display/Makefile       |   1 +
>> >  drivers/video/display/mipi-dbi-bus.c | 234 ++++++++++++++++++++++++++++++
>> >  include/video/display.h              |   4 +
>> >  include/video/mipi-dbi-bus.h         | 125 +++++++++++++++++++
>> >  5 files changed, 372 insertions(+)
>> >  create mode 100644 drivers/video/display/mipi-dbi-bus.c
>> >  create mode 100644 include/video/mipi-dbi-bus.h
>
> [snip]
>
>> > diff --git a/drivers/video/display/mipi-dbi-bus.c
>> > b/drivers/video/display/mipi-dbi-bus.c new file mode 100644
>> > index 0000000..791fb4d
>> > --- /dev/null
>> > +++ b/drivers/video/display/mipi-dbi-bus.c
>
> [snip]
>
>> > +/* ----------------------------------------------------------------------
>> > + * Device and driver (un)registration
>> > + */
>> > +
>> > +/**
>> > + * mipi_dbi_device_register - register a DBI device
>> > + * @dev: DBI device we're registering
>> > + */
>> > +int mipi_dbi_device_register(struct mipi_dbi_device *dev,
>> > +                             struct mipi_dbi_bus *bus)
>> > +{
>> > +       device_initialize(&dev->dev);
>> > +
>> > +       dev->bus = bus;
>> > +       dev->dev.bus = &mipi_dbi_bus_type;
>> > +       dev->dev.parent = bus->dev;
>> > +
>> > +       if (dev->id != -1)
>> > +               dev_set_name(&dev->dev, "%s.%d", dev->name,  dev->id);
>> > +       else
>> > +               dev_set_name(&dev->dev, "%s", dev->name);
>> > +
>> > +       return device_add(&dev->dev);
>> > +}
>>
>> The function looks very much specific to NON-DT case where you will be
>> calling mipi_dbi_device_register() in the machine file.
>
> You're absolutely right.
>
>> I was actually trying to migrate to CDFv3 and adding MIPI DSI support
>> for exynos5250,
>> but in my case where exynos5250 is fully DT based, in which case we
>> need something like ./drivers/of/platform.c for MIPI DBI and MIPI DSI
>> to add the MIPI DBI/DSI device via DT way, ./drivers/of/mipi_dbi.c and
>> ./drivers/of/mipi_dsi.c
>>
>> may look like below,
>>
>> int of_mipi_dbi_device_register(struct device_node *np,
>>                                          const char *bus_id,
>>                                          struct device *parent)
>> {
>>          struct mipi_dbi_device *dev;
>>          dev = of_device_alloc(np, bus_id, parent);
>>
>>          if (!dev)
>>                  return NULL;
>>        device_initialize(dev);
>>
>>        dev->bus = &mipi_dbi_bus_type;
>>        dev->parent = parent;
>>
>>        return of_device_add(dev);
>> }
>>
>> Correct me if I am wrong.
>
> You're correct, but the implementation will need to be a little bit more
> complex than that. From an API point of view, something like
> of_i2c_register_devices() (drivers/of/of_i2c.c) would probably make sense. the
> function should iterate over child nodes, and call
> of_mipi_dbi_device_register() (we could maybe rename that to
> of_mipi_dbi_device_create() to mimic the platform device code) for each child.
>
> In your above code, you should replace of_device_alloc() with
> of_mipi_dbi_device_alloc(), as of_device_alloc() allocates a struct
> platform_device. You should also call mipi_dsi_device_put() on the device if
> of_device_add() returns a failure.
>
> Would you like to send a patch on top of 08/19 to implement this ?
>


Sure, will send the patch to add MIPI DBI/DSI device via DT way.



>> > +EXPORT_SYMBOL_GPL(mipi_dbi_device_register);
>> > +
>> > +/**
>> > + * mipi_dbi_device_unregister - unregister a DBI device
>> > + * @dev: DBI device we're unregistering
>> > + */
>> > +void mipi_dbi_device_unregister(struct mipi_dbi_device *dev)
>> > +{
>> > +       device_del(&dev->dev);
>> > +       put_device(&dev->dev);
>> > +}
>> > +EXPORT_SYMBOL_GPL(mipi_dbi_device_unregister);
>> > +
>> > +static int mipi_dbi_drv_probe(struct device *_dev)
>> > +{
>> > +       struct mipi_dbi_driver *drv = to_mipi_dbi_driver(_dev->driver);
>> > +       struct mipi_dbi_device *dev = to_mipi_dbi_device(_dev);
>>
>> Here we are assuming that  mipi_dbi_device can be obtained by using
>> _dev pointer, which may NOT be true in DT case, i think.
>
> Why wouldn't it be true (if we create the devices as explained above) ?


Yeah, with the above method, it should be possible.


>
>> let me know if i am missing something.
>>
>> if you can give me a example for DT case, that would be helpful.
>
> I'm afraid I don't have any, as the DBI drivers I wrote are used by a platform
> that doesn't support DT.
>
>> > +
>> > +       return drv->probe(dev);
>> > +}
>
> --
> Regards,
>
> Laurent Pinchart
>



-- 
Thanks and Regards
 Vikas Sajjan

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
  2013-08-09 17:14 [PATCH/RFC v3 00/19] Common Display Framework Laurent Pinchart
                   ` (20 preceding siblings ...)
  2013-09-02 11:06 ` Tomi Valkeinen
@ 2013-09-30 13:48 ` Tomi Valkeinen
  2013-10-02 12:23     ` Andrzej Hajda
  21 siblings, 1 reply; 83+ messages in thread
From: Tomi Valkeinen @ 2013-09-30 13:48 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon


[-- Attachment #1.1: Type: text/plain, Size: 6950 bytes --]

On 09/08/13 20:14, Laurent Pinchart wrote:
> Hi everybody,
> 
> Here's the third RFC of the Common Display Framework.


Hi,

I've been trying to adapt the latest CDF RFC for OMAP. I'm trying to gather
some notes here about what I've discovered or how I see things. Some of these I
have mentioned earlier, but I'm trying to collect them here nevertheless.

I do have my branch with working DPI panel, TFP410 encoder, DVI-connector and
DSI command mode panel drivers, and modifications to make omapdss work with
CDF.  However, it's such a big hack, that I'm not going to post it. I hope I
will have time to work on it to get something publishable to have something
more concrete to present. But for the time being I have to move to other tasks
for a while, so I thought I'd better post some comments when I still remember
something about this.

Using Linux buses for DBI/DSI
=============================

I still don't see how it would work. I've covered this multiple times in
previous posts so I'm not going into more details now.

I implemented DSI (just command mode for now) as a video bus but with bunch of
extra ops for sending the control messages.

Call model
==========

It may be that I just don't get how things are supposed to work with the RFC's
ops, but I couldn't figure out how to use it in practice. I tried it for a few
days, but got nowhere, and I then went with the proven model that's used in
omapdss, where display entities handle calling the ops of the upstream
entities.

That's not to say the RFC's model doesn't work. I just didn't figure it out.
And I guess it was more difficult to understand how to use it as the controller
stuff is not implemented yet.

It would be good to have a bit more complex cases in the RFC, like changing and
verifying videomodes, fetching them via EDID, etc.

Multiple inputs/outputs
=======================

I think changing the model from single-input & single output to multiple inputs
and outputs increases the difficulty of the implementation considerably. That's
not a complaint as such, just an observation. I do think multiple inputs &
outputs is a good feature. Then again, all the use cases I have only have
single input/output, so I've been wondering if there's some middle road, in
which we somehow allow multiple inputs & outputs, but only implement the
support for single input & output.

I've cut the corners in my tests by just looking at a single enabled input or
output from an entity, and ignoring the rest (which I don't have in my use
cases).

Internal connections
====================

The model currently only represents connections between entities. With multiple
inputs & outputs I think it's important to maintain also connections inside the
entity. Say, we have an entity with two inputs and two outputs. If one output
is enabled, which one of the inputs needs to be enabled and configured also?
The current model doesn't give any solution to that.

I haven't implemented this, as in my use cases I have just single inputs and
outputs, so I can follow the pipeline trivially.

Central entity
==============

If I understand the RFC correctly, there's a "central" entity that manages all
other entities connected to it. This central entity would normally be the
display controller. I don't like this model, as it makes it difficult or
impossible to manage situations where an entity is connected to two display
controllers (even if only one of the display controllers would be connected at
a time). It also makes this one display entity fundamentally different from the
others, which I don't like.

I think all the display entities should be similar. They would all register
themselves to the CDF framework, which in turn would be used by somebody. This
somebody could be the display controller driver, which is more or less how I've
implemented it.

Media entity/pads
=================

Using media_entity and media_pad fits quite well for CDF, but... It is quite
cumbersome to use. The constant switching between media_entity and
display_entity needs quite a lot of code in total, as it has to be done almost
everywhere.

And somehow I'd really like to combine the entity and port into one struct so
that it would be possible to just do:

src->ops->foo(src, ...);

instead of

src->ops->foo(src, srcport, ...);

One reason is that the latter is more verbose (not only the call, you also need
to get srcport from somewhere), but also that as far as the caller is
concerned, there's no reason to manage the entity and the port as separate
things. You just want a particular video source/sink to do something, and
whether that source/sink is port 5 of entity foo is irrelevant.

The callee, of course, needs to check which port is being operated. However,
if, say, 90% of the display entities have just one input and one output port,
the port parameter can be ignored for those entities, simplifying the code.

And while media_entity can be embedded into display_entity, media_pad and
media_link cannot be embedded into anything. This is somewhat vague as I don't
quite remember what my reason for needing the feature was, but I had some need
for display_link or display_pad, to add some CDF related entries, which can't
be done except by modifying the media_link or media_pad themselves.

DT data & platform data
=======================

I think the V4L2 style port/endpoint description in DT data should work well. I
don't see a need for specifying the remote-endpoint in the upstream entity, but
then again, it doesn't hurt either.

The description does get pretty verbose, though, but I guess that can't be
avoided.

Describing similar things in the platform data works fine too. The RFC,
however, contained somewhat lacking platform data examples which had to be
extended to work with, for example, multiple instances of the same display
entity. Also, the RFC relied on the central entity to parse the platform data,
and in my model each display entity has its own platform data.

Final thoughts
==============

So many of the comments above are somewhat gut-feelings. I don't have concrete
evidence that my ideas are better, as I haven't been able to finalize the code
(well, and the RFC is missing important things like the controller).

I think there are areas where my model and the RFC are similar. I think one
step would be to identify those parts, and perhaps have those parts as separate
pieces of code. Say, the DT and platform data parts might be such that we could
have display-of.c and display-pdata.c, having support code which works for the
RFC and my model.

This would make it easier to maintain and improve both versions, to see how
they evolve and what are the pros and cons with both models. But this is just a
thought, I'm not sure how much such code there would actually be.

 Tomi




[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

[-- Attachment #2: Type: text/plain, Size: 159 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
  2013-09-30 13:48 ` Tomi Valkeinen
@ 2013-10-02 12:23     ` Andrzej Hajda
  0 siblings, 0 replies; 83+ messages in thread
From: Andrzej Hajda @ 2013-10-02 12:23 UTC (permalink / raw)
  To: Tomi Valkeinen, Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

Hi Tomi,

On 09/30/2013 03:48 PM, Tomi Valkeinen wrote:
> On 09/08/13 20:14, Laurent Pinchart wrote:
>> Hi everybody,
>>
>> Here's the third RFC of the Common Display Framework.
> 
> 
> Hi,
> 
> I've been trying to adapt the latest CDF RFC for OMAP. I'm trying to gather
> some notes here about what I've discovered or how I see things. Some of these I
> have mentioned earlier, but I'm trying to collect them here nevertheless.
> 
> I do have my branch with working DPI panel, TFP410 encoder, DVI-connector and
> DSI command mode panel drivers, and modifications to make omapdss work with
> CDF.  However, it's such a big hack, that I'm not going to post it. I hope I
> will have time to work on it to get something publishable to have something
> more concrete to present. But for the time being I have to move to other tasks
> for a while, so I thought I'd better post some comments when I still remember
> something about this.
> 
> Using Linux buses for DBI/DSI
> =============================
> 
> I still don't see how it would work. I've covered this multiple times in
> previous posts so I'm not going into more details now.
> 
> I implemented DSI (just command mode for now) as a video bus but with bunch of
> extra ops for sending the control messages.

Could you post the list of ops you have to create.

I have posted some time ago my implementation of DSI bus:
http://thread.gmane.org/gmane.linux.drivers.video-input-infrastructure/69358/focus=69362

I needed three quite generic ops to make it working:
- set_power(on/off),
- set_stream(on/off),
- transfer(dsi_transaction_type, tx_buf, tx_len, rx_buf, rx_len)
I have recently replaced set_power by PM_RUNTIME callbacks,
but I had to add .initialize ops.

Regarding the discussion how and where to implement control bus I have
though about different alternatives:
1. Implement DSI-master as a parent dev which will create DSI-slave
platform dev in a similar way as for MFD devices (ssbi.c seems to me a
good example).
2. Create universal mipi-display-bus which will cover DSI, DBI and
possibly other buses - they have have few common things - for example
MIPI-DCS commands.

I am not really convinced to either solution all have some advantages
and disadvantages.


> 
> Call model
> ==========
> 
> It may be that I just don't get how things are supposed to work with the RFC's
> ops, but I couldn't figure out how to use it in practice. I tried it for a few
> days, but got nowhere, and I then went with the proven model that's used in
> omapdss, where display entities handle calling the ops of the upstream
> entities.
> 
> That's not to say the RFC's model doesn't work. I just didn't figure it out.
> And I guess it was more difficult to understand how to use it as the controller
> stuff is not implemented yet.
> 
> It would be good to have a bit more complex cases in the RFC, like changing and
> verifying videomodes, fetching them via EDID, etc.
> 
> Multiple inputs/outputs
> =======================
> 
> I think changing the model from single-input & single output to multiple inputs
> and outputs increases the difficulty of the implementation considerably. That's
> not a complaint as such, just an observation. I do think multiple inputs &
> outputs is a good feature. Then again, all the use cases I have only have
> single input/output, so I've been wondering if there's some middle road, in
> which we somehow allow multiple inputs & outputs, but only implement the
> support for single input & output.
> 
> I've cut the corners in my tests by just looking at a single enabled input or
> output from an entity, and ignoring the rest (which I don't have in my use
> cases).
> 
> Internal connections
> ====================
> 
> The model currently only represents connections between entities. With multiple
> inputs & outputs I think it's important to maintain also connections inside the
> entity. Say, we have an entity with two inputs and two outputs. If one output
> is enabled, which one of the inputs needs to be enabled and configured also?
> The current model doesn't give any solution to that.
> 
> I haven't implemented this, as in my use cases I have just single inputs and
> outputs, so I can follow the pipeline trivially.
> 
> Central entity
> ==============
> 
> If I understand the RFC correctly, there's a "central" entity that manages all
> other entities connected to it. This central entity would normally be the
> display controller. I don't like this model, as it makes it difficult or
> impossible to manage situations where an entity is connected to two display
> controllers (even if only one of the display controllers would be connected at
> a time). It also makes this one display entity fundamentally different from the
> others, which I don't like.
> 
> I think all the display entities should be similar. They would all register
> themselves to the CDF framework, which in turn would be used by somebody. This
> somebody could be the display controller driver, which is more or less how I've
> implemented it.
> 
> Media entity/pads
> =================
> 
> Using media_entity and media_pad fits quite well for CDF, but... It is quite
> cumbersome to use. The constant switching between media_entity and
> display_entity needs quite a lot of code in total, as it has to be done almost
> everywhere.
> 
> And somehow I'd really like to combine the entity and port into one struct so
> that it would be possible to just do:
> 
> src->ops->foo(src, ...);
> 
> instead of
> 
> src->ops->foo(src, srcport, ...);
> 
> One reason is that the latter is more verbose (not only the call, you also need
> to get srcport from somewhere), but also that as far as the caller is
> concerned, there's no reason to manage the entity and the port as separate
> things. You just want a particular video source/sink to do something, and
> whether that source/sink is port 5 of entity foo is irrelevant.
> 
> The callee, of course, needs to check which port is being operated. However,
> if, say, 90% of the display entities have just one input and one output port,
> the port parameter can be ignored for those entities, simplifying the code.
> 
> And while media_entity can be embedded into display_entity, media_pad and
> media_link cannot be embedded into anything. This is somewhat vague as I don't
> quite remember what my reason for needing the feature was, but I had some need
> for display_link or display_pad, to add some CDF related entries, which can't
> be done except by modifying the media_link or media_pad themselves.
> 
> DT data & platform data
> =======================
> 
> I think the V4L2 style port/endpoint description in DT data should work well. I
> don't see a need for specifying the remote-endpoint in the upstream entity, but
> then again, it doesn't hurt either.
> 
> The description does get pretty verbose, though, but I guess that can't be
> avoided.
> 
> Describing similar things in the platform data works fine too. The RFC,
> however, contained somewhat lacking platform data examples which had to be
> extended to work with, for example, multiple instances of the same display
> entity. Also, the RFC relied on the central entity to parse the platform data,
> and in my model each display entity has its own platform data.
> 
> Final thoughts
> ==============
> 
> So many of the comments above are somewhat gut-feelings. I don't have concrete
> evidence that my ideas are better, as I haven't been able to finalize the code
> (well, and the RFC is missing important things like the controller).
> 
> I think there are areas where my model and the RFC are similar. I think one
> step would be to identify those parts, and perhaps have those parts as separate
> pieces of code. Say, the DT and platform data parts might be such that we could
> have display-of.c and display-pdata.c, having support code which works for the
> RFC and my model.
> 
> This would make it easier to maintain and improve both versions, to see how
> they evolve and what are the pros and cons with both models. But this is just a
> thought, I'm not sure how much such code there would actually be.
> 
>  Tomi
> 
> 
> 
> 
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
> 


^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
@ 2013-10-02 12:23     ` Andrzej Hajda
  0 siblings, 0 replies; 83+ messages in thread
From: Andrzej Hajda @ 2013-10-02 12:23 UTC (permalink / raw)
  To: Tomi Valkeinen, Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

Hi Tomi,

On 09/30/2013 03:48 PM, Tomi Valkeinen wrote:
> On 09/08/13 20:14, Laurent Pinchart wrote:
>> Hi everybody,
>>
>> Here's the third RFC of the Common Display Framework.
> 
> 
> Hi,
> 
> I've been trying to adapt the latest CDF RFC for OMAP. I'm trying to gather
> some notes here about what I've discovered or how I see things. Some of these I
> have mentioned earlier, but I'm trying to collect them here nevertheless.
> 
> I do have my branch with working DPI panel, TFP410 encoder, DVI-connector and
> DSI command mode panel drivers, and modifications to make omapdss work with
> CDF.  However, it's such a big hack, that I'm not going to post it. I hope I
> will have time to work on it to get something publishable to have something
> more concrete to present. But for the time being I have to move to other tasks
> for a while, so I thought I'd better post some comments when I still remember
> something about this.
> 
> Using Linux buses for DBI/DSI
> ==============> 
> I still don't see how it would work. I've covered this multiple times in
> previous posts so I'm not going into more details now.
> 
> I implemented DSI (just command mode for now) as a video bus but with bunch of
> extra ops for sending the control messages.

Could you post the list of ops you have to create.

I have posted some time ago my implementation of DSI bus:
http://thread.gmane.org/gmane.linux.drivers.video-input-infrastructure/69358/focusi362

I needed three quite generic ops to make it working:
- set_power(on/off),
- set_stream(on/off),
- transfer(dsi_transaction_type, tx_buf, tx_len, rx_buf, rx_len)
I have recently replaced set_power by PM_RUNTIME callbacks,
but I had to add .initialize ops.

Regarding the discussion how and where to implement control bus I have
though about different alternatives:
1. Implement DSI-master as a parent dev which will create DSI-slave
platform dev in a similar way as for MFD devices (ssbi.c seems to me a
good example).
2. Create universal mipi-display-bus which will cover DSI, DBI and
possibly other buses - they have have few common things - for example
MIPI-DCS commands.

I am not really convinced to either solution all have some advantages
and disadvantages.


> 
> Call model
> =====
> 
> It may be that I just don't get how things are supposed to work with the RFC's
> ops, but I couldn't figure out how to use it in practice. I tried it for a few
> days, but got nowhere, and I then went with the proven model that's used in
> omapdss, where display entities handle calling the ops of the upstream
> entities.
> 
> That's not to say the RFC's model doesn't work. I just didn't figure it out.
> And I guess it was more difficult to understand how to use it as the controller
> stuff is not implemented yet.
> 
> It would be good to have a bit more complex cases in the RFC, like changing and
> verifying videomodes, fetching them via EDID, etc.
> 
> Multiple inputs/outputs
> ===========> 
> I think changing the model from single-input & single output to multiple inputs
> and outputs increases the difficulty of the implementation considerably. That's
> not a complaint as such, just an observation. I do think multiple inputs &
> outputs is a good feature. Then again, all the use cases I have only have
> single input/output, so I've been wondering if there's some middle road, in
> which we somehow allow multiple inputs & outputs, but only implement the
> support for single input & output.
> 
> I've cut the corners in my tests by just looking at a single enabled input or
> output from an entity, and ignoring the rest (which I don't have in my use
> cases).
> 
> Internal connections
> ==========
> 
> The model currently only represents connections between entities. With multiple
> inputs & outputs I think it's important to maintain also connections inside the
> entity. Say, we have an entity with two inputs and two outputs. If one output
> is enabled, which one of the inputs needs to be enabled and configured also?
> The current model doesn't give any solution to that.
> 
> I haven't implemented this, as in my use cases I have just single inputs and
> outputs, so I can follow the pipeline trivially.
> 
> Central entity
> =======
> 
> If I understand the RFC correctly, there's a "central" entity that manages all
> other entities connected to it. This central entity would normally be the
> display controller. I don't like this model, as it makes it difficult or
> impossible to manage situations where an entity is connected to two display
> controllers (even if only one of the display controllers would be connected at
> a time). It also makes this one display entity fundamentally different from the
> others, which I don't like.
> 
> I think all the display entities should be similar. They would all register
> themselves to the CDF framework, which in turn would be used by somebody. This
> somebody could be the display controller driver, which is more or less how I've
> implemented it.
> 
> Media entity/pads
> ========> 
> Using media_entity and media_pad fits quite well for CDF, but... It is quite
> cumbersome to use. The constant switching between media_entity and
> display_entity needs quite a lot of code in total, as it has to be done almost
> everywhere.
> 
> And somehow I'd really like to combine the entity and port into one struct so
> that it would be possible to just do:
> 
> src->ops->foo(src, ...);
> 
> instead of
> 
> src->ops->foo(src, srcport, ...);
> 
> One reason is that the latter is more verbose (not only the call, you also need
> to get srcport from somewhere), but also that as far as the caller is
> concerned, there's no reason to manage the entity and the port as separate
> things. You just want a particular video source/sink to do something, and
> whether that source/sink is port 5 of entity foo is irrelevant.
> 
> The callee, of course, needs to check which port is being operated. However,
> if, say, 90% of the display entities have just one input and one output port,
> the port parameter can be ignored for those entities, simplifying the code.
> 
> And while media_entity can be embedded into display_entity, media_pad and
> media_link cannot be embedded into anything. This is somewhat vague as I don't
> quite remember what my reason for needing the feature was, but I had some need
> for display_link or display_pad, to add some CDF related entries, which can't
> be done except by modifying the media_link or media_pad themselves.
> 
> DT data & platform data
> ===========> 
> I think the V4L2 style port/endpoint description in DT data should work well. I
> don't see a need for specifying the remote-endpoint in the upstream entity, but
> then again, it doesn't hurt either.
> 
> The description does get pretty verbose, though, but I guess that can't be
> avoided.
> 
> Describing similar things in the platform data works fine too. The RFC,
> however, contained somewhat lacking platform data examples which had to be
> extended to work with, for example, multiple instances of the same display
> entity. Also, the RFC relied on the central entity to parse the platform data,
> and in my model each display entity has its own platform data.
> 
> Final thoughts
> =======
> 
> So many of the comments above are somewhat gut-feelings. I don't have concrete
> evidence that my ideas are better, as I haven't been able to finalize the code
> (well, and the RFC is missing important things like the controller).
> 
> I think there are areas where my model and the RFC are similar. I think one
> step would be to identify those parts, and perhaps have those parts as separate
> pieces of code. Say, the DT and platform data parts might be such that we could
> have display-of.c and display-pdata.c, having support code which works for the
> RFC and my model.
> 
> This would make it easier to maintain and improve both versions, to see how
> they evolve and what are the pros and cons with both models. But this is just a
> thought, I'm not sure how much such code there would actually be.
> 
>  Tomi
> 
> 
> 
> 
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
> 


^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
  2013-10-02 12:23     ` Andrzej Hajda
  (?)
@ 2013-10-02 13:24       ` Tomi Valkeinen
  -1 siblings, 0 replies; 83+ messages in thread
From: Tomi Valkeinen @ 2013-10-02 13:24 UTC (permalink / raw)
  To: Andrzej Hajda
  Cc: Laurent Pinchart, linux-fbdev, dri-devel, Jesse Barnes,
	Benjamin Gaignard, Tom Gall, Kyungmin Park, linux-media,
	Stephen Warren, Mark Zhang, Alexandre Courbot,
	Ragesh Radhakrishnan, Thomas Petazzoni, Sunil Joshi,
	Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

[-- Attachment #1: Type: text/plain, Size: 3871 bytes --]

Hi Andrzej,

On 02/10/13 15:23, Andrzej Hajda wrote:

>> Using Linux buses for DBI/DSI
>> =============================
>>
>> I still don't see how it would work. I've covered this multiple times in
>> previous posts so I'm not going into more details now.
>>
>> I implemented DSI (just command mode for now) as a video bus but with bunch of
>> extra ops for sending the control messages.
> 
> Could you post the list of ops you have to create.

I'd rather not post the ops I have in my prototype, as it's still a
total hack. However, they are very much based on the current OMAP DSS's
ops, so I'll describe them below. I hope I find time to polish my CDF
hacks more, so that I can publish them.

> I have posted some time ago my implementation of DSI bus:
> http://thread.gmane.org/gmane.linux.drivers.video-input-infrastructure/69358/focus=69362

A note about the DT data on your series, as I've been stuggling to
figure out the DT data for OMAP: some of the DT properties look like
configuration, not hardware description. For example,
"samsung,bta-timeout" doesn't describe hardware.

> I needed three quite generic ops to make it working:
> - set_power(on/off),
> - set_stream(on/off),
> - transfer(dsi_transaction_type, tx_buf, tx_len, rx_buf, rx_len)
> I have recently replaced set_power by PM_RUNTIME callbacks,
> but I had to add .initialize ops.

We have a bit more on omap:

http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/video/omapdss.h#n648

Some of those should be removed and some should be omap DSI's internal
matters, not part of the API. But it gives an idea of the ops we use.
Shortly about the ops:

- (dis)connect, which might be similar to your initialize. connect is
meant to "connect" the pipeline, reserving the video ports used, etc.

- enable/disable, enable the DSI bus. If the DSI peripheral requires a
continous DSI clock, it's also started at this point.

- set_config configures the DSI bus (like, command/video mode, etc.).

- configure_pins can be ignored, I think that function is not needed.

- enable_hs and enable_te, used to enable/disable HS mode and
tearing-elimination

- update, which does a single frame transfer

- bus_lock/unlock can be ignored

- enable_video_output starts the video stream, when using DSI video mode

- the request_vc, set_vc_id, release_vc can be ignored

- Bunch of transfer funcs. Perhaps a single func could be used, as you
do. We have sync write funcs, which do a BTA at the end of the write and
wait for reply, and nosync version, which just pushes the packet to the
TX buffers.

- bta_sync, which sends a BTA and waits for the peripheral to reply

- set_max_rx_packet_size, used to configure the max rx packet size.

> Regarding the discussion how and where to implement control bus I have
> though about different alternatives:
> 1. Implement DSI-master as a parent dev which will create DSI-slave
> platform dev in a similar way as for MFD devices (ssbi.c seems to me a
> good example).
> 2. Create universal mipi-display-bus which will cover DSI, DBI and
> possibly other buses - they have have few common things - for example
> MIPI-DCS commands.
> 
> I am not really convinced to either solution all have some advantages
> and disadvantages.

I think a dedicated DSI bus and your alternatives all have the same
issues with splitting the DSI control into two. I've shared some of my
thoughts here:

http://article.gmane.org/gmane.comp.video.dri.devel/90651
http://article.gmane.org/gmane.comp.video.dri.devel/91269
http://article.gmane.org/gmane.comp.video.dri.devel/91272

I still think that it's best to consider DSI and DBI as a video bus (not
as a separate video bus and a control bus), and provide the packet
transfer methods as part of the video ops.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
@ 2013-10-02 13:24       ` Tomi Valkeinen
  0 siblings, 0 replies; 83+ messages in thread
From: Tomi Valkeinen @ 2013-10-02 13:24 UTC (permalink / raw)
  To: Andrzej Hajda
  Cc: Laurent Pinchart, linux-fbdev, dri-devel, Jesse Barnes,
	Benjamin Gaignard, Tom Gall, Kyungmin Park, linux-media,
	Stephen Warren, Mark Zhang, Alexandre Courbot,
	Ragesh Radhakrishnan, Thomas Petazzoni, Sunil Joshi,
	Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

[-- Attachment #1: Type: text/plain, Size: 3871 bytes --]

Hi Andrzej,

On 02/10/13 15:23, Andrzej Hajda wrote:

>> Using Linux buses for DBI/DSI
>> =============================
>>
>> I still don't see how it would work. I've covered this multiple times in
>> previous posts so I'm not going into more details now.
>>
>> I implemented DSI (just command mode for now) as a video bus but with bunch of
>> extra ops for sending the control messages.
> 
> Could you post the list of ops you have to create.

I'd rather not post the ops I have in my prototype, as it's still a
total hack. However, they are very much based on the current OMAP DSS's
ops, so I'll describe them below. I hope I find time to polish my CDF
hacks more, so that I can publish them.

> I have posted some time ago my implementation of DSI bus:
> http://thread.gmane.org/gmane.linux.drivers.video-input-infrastructure/69358/focus=69362

A note about the DT data on your series, as I've been stuggling to
figure out the DT data for OMAP: some of the DT properties look like
configuration, not hardware description. For example,
"samsung,bta-timeout" doesn't describe hardware.

> I needed three quite generic ops to make it working:
> - set_power(on/off),
> - set_stream(on/off),
> - transfer(dsi_transaction_type, tx_buf, tx_len, rx_buf, rx_len)
> I have recently replaced set_power by PM_RUNTIME callbacks,
> but I had to add .initialize ops.

We have a bit more on omap:

http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/video/omapdss.h#n648

Some of those should be removed and some should be omap DSI's internal
matters, not part of the API. But it gives an idea of the ops we use.
Shortly about the ops:

- (dis)connect, which might be similar to your initialize. connect is
meant to "connect" the pipeline, reserving the video ports used, etc.

- enable/disable, enable the DSI bus. If the DSI peripheral requires a
continous DSI clock, it's also started at this point.

- set_config configures the DSI bus (like, command/video mode, etc.).

- configure_pins can be ignored, I think that function is not needed.

- enable_hs and enable_te, used to enable/disable HS mode and
tearing-elimination

- update, which does a single frame transfer

- bus_lock/unlock can be ignored

- enable_video_output starts the video stream, when using DSI video mode

- the request_vc, set_vc_id, release_vc can be ignored

- Bunch of transfer funcs. Perhaps a single func could be used, as you
do. We have sync write funcs, which do a BTA at the end of the write and
wait for reply, and nosync version, which just pushes the packet to the
TX buffers.

- bta_sync, which sends a BTA and waits for the peripheral to reply

- set_max_rx_packet_size, used to configure the max rx packet size.

> Regarding the discussion how and where to implement control bus I have
> though about different alternatives:
> 1. Implement DSI-master as a parent dev which will create DSI-slave
> platform dev in a similar way as for MFD devices (ssbi.c seems to me a
> good example).
> 2. Create universal mipi-display-bus which will cover DSI, DBI and
> possibly other buses - they have have few common things - for example
> MIPI-DCS commands.
> 
> I am not really convinced to either solution all have some advantages
> and disadvantages.

I think a dedicated DSI bus and your alternatives all have the same
issues with splitting the DSI control into two. I've shared some of my
thoughts here:

http://article.gmane.org/gmane.comp.video.dri.devel/90651
http://article.gmane.org/gmane.comp.video.dri.devel/91269
http://article.gmane.org/gmane.comp.video.dri.devel/91272

I still think that it's best to consider DSI and DBI as a video bus (not
as a separate video bus and a control bus), and provide the packet
transfer methods as part of the video ops.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
@ 2013-10-02 13:24       ` Tomi Valkeinen
  0 siblings, 0 replies; 83+ messages in thread
From: Tomi Valkeinen @ 2013-10-02 13:24 UTC (permalink / raw)
  To: Andrzej Hajda
  Cc: Laurent Pinchart, linux-fbdev, dri-devel, Jesse Barnes,
	Benjamin Gaignard, Tom Gall, Kyungmin Park, linux-media,
	Stephen Warren, Mark Zhang, Alexandre Courbot,
	Ragesh Radhakrishnan, Thomas Petazzoni, Sunil Joshi,
	Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

[-- Attachment #1: Type: text/plain, Size: 3871 bytes --]

Hi Andrzej,

On 02/10/13 15:23, Andrzej Hajda wrote:

>> Using Linux buses for DBI/DSI
>> =============================
>>
>> I still don't see how it would work. I've covered this multiple times in
>> previous posts so I'm not going into more details now.
>>
>> I implemented DSI (just command mode for now) as a video bus but with bunch of
>> extra ops for sending the control messages.
> 
> Could you post the list of ops you have to create.

I'd rather not post the ops I have in my prototype, as it's still a
total hack. However, they are very much based on the current OMAP DSS's
ops, so I'll describe them below. I hope I find time to polish my CDF
hacks more, so that I can publish them.

> I have posted some time ago my implementation of DSI bus:
> http://thread.gmane.org/gmane.linux.drivers.video-input-infrastructure/69358/focus=69362

A note about the DT data on your series, as I've been stuggling to
figure out the DT data for OMAP: some of the DT properties look like
configuration, not hardware description. For example,
"samsung,bta-timeout" doesn't describe hardware.

> I needed three quite generic ops to make it working:
> - set_power(on/off),
> - set_stream(on/off),
> - transfer(dsi_transaction_type, tx_buf, tx_len, rx_buf, rx_len)
> I have recently replaced set_power by PM_RUNTIME callbacks,
> but I had to add .initialize ops.

We have a bit more on omap:

http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/video/omapdss.h#n648

Some of those should be removed and some should be omap DSI's internal
matters, not part of the API. But it gives an idea of the ops we use.
Shortly about the ops:

- (dis)connect, which might be similar to your initialize. connect is
meant to "connect" the pipeline, reserving the video ports used, etc.

- enable/disable, enable the DSI bus. If the DSI peripheral requires a
continous DSI clock, it's also started at this point.

- set_config configures the DSI bus (like, command/video mode, etc.).

- configure_pins can be ignored, I think that function is not needed.

- enable_hs and enable_te, used to enable/disable HS mode and
tearing-elimination

- update, which does a single frame transfer

- bus_lock/unlock can be ignored

- enable_video_output starts the video stream, when using DSI video mode

- the request_vc, set_vc_id, release_vc can be ignored

- Bunch of transfer funcs. Perhaps a single func could be used, as you
do. We have sync write funcs, which do a BTA at the end of the write and
wait for reply, and nosync version, which just pushes the packet to the
TX buffers.

- bta_sync, which sends a BTA and waits for the peripheral to reply

- set_max_rx_packet_size, used to configure the max rx packet size.

> Regarding the discussion how and where to implement control bus I have
> though about different alternatives:
> 1. Implement DSI-master as a parent dev which will create DSI-slave
> platform dev in a similar way as for MFD devices (ssbi.c seems to me a
> good example).
> 2. Create universal mipi-display-bus which will cover DSI, DBI and
> possibly other buses - they have have few common things - for example
> MIPI-DCS commands.
> 
> I am not really convinced to either solution all have some advantages
> and disadvantages.

I think a dedicated DSI bus and your alternatives all have the same
issues with splitting the DSI control into two. I've shared some of my
thoughts here:

http://article.gmane.org/gmane.comp.video.dri.devel/90651
http://article.gmane.org/gmane.comp.video.dri.devel/91269
http://article.gmane.org/gmane.comp.video.dri.devel/91272

I still think that it's best to consider DSI and DBI as a video bus (not
as a separate video bus and a control bus), and provide the packet
transfer methods as part of the video ops.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
  2013-10-02 13:24       ` Tomi Valkeinen
@ 2013-10-09 14:08         ` Andrzej Hajda
  -1 siblings, 0 replies; 83+ messages in thread
From: Andrzej Hajda @ 2013-10-09 14:08 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Laurent Pinchart, linux-fbdev, dri-devel, Jesse Barnes,
	Benjamin Gaignard, Tom Gall, Kyungmin Park, linux-media,
	Stephen Warren, Mark Zhang, Alexandre Courbot,
	Ragesh Radhakrishnan, Thomas Petazzoni, Sunil Joshi,
	Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

On 10/02/2013 03:24 PM, Tomi Valkeinen wrote:
> Hi Andrzej,
>
> On 02/10/13 15:23, Andrzej Hajda wrote:
>
>>> Using Linux buses for DBI/DSI
>>> =============================
>>>
>>> I still don't see how it would work. I've covered this multiple times in
>>> previous posts so I'm not going into more details now.
>>>
>>> I implemented DSI (just command mode for now) as a video bus but with bunch of
>>> extra ops for sending the control messages.
>> Could you post the list of ops you have to create.
> I'd rather not post the ops I have in my prototype, as it's still a
> total hack. However, they are very much based on the current OMAP DSS's
> ops, so I'll describe them below. I hope I find time to polish my CDF
> hacks more, so that I can publish them.
>
>> I have posted some time ago my implementation of DSI bus:
>> http://thread.gmane.org/gmane.linux.drivers.video-input-infrastructure/69358/focus=69362
> A note about the DT data on your series, as I've been stuggling to
> figure out the DT data for OMAP: some of the DT properties look like
> configuration, not hardware description. For example,
> "samsung,bta-timeout" doesn't describe hardware.
As I have adopted existing internal driver for MIPI-DSI bus, I did not
take too much
care for DT. You are right, 'bta-timeout' is a configuration parameter
(however its
minimal value is determined by characteristic of the DSI-slave). On the
other
side currently there is no good place for such configuration parameters
AFAIK.
>> I needed three quite generic ops to make it working:
>> - set_power(on/off),
>> - set_stream(on/off),
>> - transfer(dsi_transaction_type, tx_buf, tx_len, rx_buf, rx_len)
>> I have recently replaced set_power by PM_RUNTIME callbacks,
>> but I had to add .initialize ops.
> We have a bit more on omap:
>
> http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/video/omapdss.h#n648
>
> Some of those should be removed and some should be omap DSI's internal
> matters, not part of the API. But it gives an idea of the ops we use.
> Shortly about the ops:
>
> - (dis)connect, which might be similar to your initialize. connect is
> meant to "connect" the pipeline, reserving the video ports used, etc.
>
> - enable/disable, enable the DSI bus. If the DSI peripheral requires a
> continous DSI clock, it's also started at this point.
>
> - set_config configures the DSI bus (like, command/video mode, etc.).
>
> - configure_pins can be ignored, I think that function is not needed.
>
> - enable_hs and enable_te, used to enable/disable HS mode and
> tearing-elimination

It seems there should be a way to synchronize TE signal with panel,
in case signal is provided only to dsi-master. Some callback I suppose?
Or transfer synchronization should be done by dsi-master.
>
> - update, which does a single frame transfer
>
> - bus_lock/unlock can be ignored
>
> - enable_video_output starts the video stream, when using DSI video mode
>
> - the request_vc, set_vc_id, release_vc can be ignored
>
> - Bunch of transfer funcs. Perhaps a single func could be used, as you
> do. We have sync write funcs, which do a BTA at the end of the write and
> wait for reply, and nosync version, which just pushes the packet to the
> TX buffers.
>
> - bta_sync, which sends a BTA and waits for the peripheral to reply
>
> - set_max_rx_packet_size, used to configure the max rx packet size.
Similar callbacks should be added to mipi-dsi-bus ops as well, to
make it complete/generic.

>
>> Regarding the discussion how and where to implement control bus I have
>> though about different alternatives:
>> 1. Implement DSI-master as a parent dev which will create DSI-slave
>> platform dev in a similar way as for MFD devices (ssbi.c seems to me a
>> good example).
>> 2. Create universal mipi-display-bus which will cover DSI, DBI and
>> possibly other buses - they have have few common things - for example
>> MIPI-DCS commands.
>>
>> I am not really convinced to either solution all have some advantages
>> and disadvantages.
> I think a dedicated DSI bus and your alternatives all have the same
> issues with splitting the DSI control into two. I've shared some of my
> thoughts here:
>
> http://article.gmane.org/gmane.comp.video.dri.devel/90651
> http://article.gmane.org/gmane.comp.video.dri.devel/91269
> http://article.gmane.org/gmane.comp.video.dri.devel/91272
>
> I still think that it's best to consider DSI and DBI as a video bus (not
> as a separate video bus and a control bus), and provide the packet
> transfer methods as part of the video ops.
I have read all posts regarding this issue and currently I tend
to solution where CDF is used to model only video streams,
with control bus implemented in different framework.
The only concerns I have if we should use Linux bus for that.

Andrzej

>  Tomi
>
>


^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
@ 2013-10-09 14:08         ` Andrzej Hajda
  0 siblings, 0 replies; 83+ messages in thread
From: Andrzej Hajda @ 2013-10-09 14:08 UTC (permalink / raw)
  To: Tomi Valkeinen
  Cc: Laurent Pinchart, linux-fbdev, dri-devel, Jesse Barnes,
	Benjamin Gaignard, Tom Gall, Kyungmin Park, linux-media,
	Stephen Warren, Mark Zhang, Alexandre Courbot,
	Ragesh Radhakrishnan, Thomas Petazzoni, Sunil Joshi,
	Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

On 10/02/2013 03:24 PM, Tomi Valkeinen wrote:
> Hi Andrzej,
>
> On 02/10/13 15:23, Andrzej Hajda wrote:
>
>>> Using Linux buses for DBI/DSI
>>> ==============>>>
>>> I still don't see how it would work. I've covered this multiple times in
>>> previous posts so I'm not going into more details now.
>>>
>>> I implemented DSI (just command mode for now) as a video bus but with bunch of
>>> extra ops for sending the control messages.
>> Could you post the list of ops you have to create.
> I'd rather not post the ops I have in my prototype, as it's still a
> total hack. However, they are very much based on the current OMAP DSS's
> ops, so I'll describe them below. I hope I find time to polish my CDF
> hacks more, so that I can publish them.
>
>> I have posted some time ago my implementation of DSI bus:
>> http://thread.gmane.org/gmane.linux.drivers.video-input-infrastructure/69358/focusi362
> A note about the DT data on your series, as I've been stuggling to
> figure out the DT data for OMAP: some of the DT properties look like
> configuration, not hardware description. For example,
> "samsung,bta-timeout" doesn't describe hardware.
As I have adopted existing internal driver for MIPI-DSI bus, I did not
take too much
care for DT. You are right, 'bta-timeout' is a configuration parameter
(however its
minimal value is determined by characteristic of the DSI-slave). On the
other
side currently there is no good place for such configuration parameters
AFAIK.
>> I needed three quite generic ops to make it working:
>> - set_power(on/off),
>> - set_stream(on/off),
>> - transfer(dsi_transaction_type, tx_buf, tx_len, rx_buf, rx_len)
>> I have recently replaced set_power by PM_RUNTIME callbacks,
>> but I had to add .initialize ops.
> We have a bit more on omap:
>
> http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/video/omapdss.h#n648
>
> Some of those should be removed and some should be omap DSI's internal
> matters, not part of the API. But it gives an idea of the ops we use.
> Shortly about the ops:
>
> - (dis)connect, which might be similar to your initialize. connect is
> meant to "connect" the pipeline, reserving the video ports used, etc.
>
> - enable/disable, enable the DSI bus. If the DSI peripheral requires a
> continous DSI clock, it's also started at this point.
>
> - set_config configures the DSI bus (like, command/video mode, etc.).
>
> - configure_pins can be ignored, I think that function is not needed.
>
> - enable_hs and enable_te, used to enable/disable HS mode and
> tearing-elimination

It seems there should be a way to synchronize TE signal with panel,
in case signal is provided only to dsi-master. Some callback I suppose?
Or transfer synchronization should be done by dsi-master.
>
> - update, which does a single frame transfer
>
> - bus_lock/unlock can be ignored
>
> - enable_video_output starts the video stream, when using DSI video mode
>
> - the request_vc, set_vc_id, release_vc can be ignored
>
> - Bunch of transfer funcs. Perhaps a single func could be used, as you
> do. We have sync write funcs, which do a BTA at the end of the write and
> wait for reply, and nosync version, which just pushes the packet to the
> TX buffers.
>
> - bta_sync, which sends a BTA and waits for the peripheral to reply
>
> - set_max_rx_packet_size, used to configure the max rx packet size.
Similar callbacks should be added to mipi-dsi-bus ops as well, to
make it complete/generic.

>
>> Regarding the discussion how and where to implement control bus I have
>> though about different alternatives:
>> 1. Implement DSI-master as a parent dev which will create DSI-slave
>> platform dev in a similar way as for MFD devices (ssbi.c seems to me a
>> good example).
>> 2. Create universal mipi-display-bus which will cover DSI, DBI and
>> possibly other buses - they have have few common things - for example
>> MIPI-DCS commands.
>>
>> I am not really convinced to either solution all have some advantages
>> and disadvantages.
> I think a dedicated DSI bus and your alternatives all have the same
> issues with splitting the DSI control into two. I've shared some of my
> thoughts here:
>
> http://article.gmane.org/gmane.comp.video.dri.devel/90651
> http://article.gmane.org/gmane.comp.video.dri.devel/91269
> http://article.gmane.org/gmane.comp.video.dri.devel/91272
>
> I still think that it's best to consider DSI and DBI as a video bus (not
> as a separate video bus and a control bus), and provide the packet
> transfer methods as part of the video ops.
I have read all posts regarding this issue and currently I tend
to solution where CDF is used to model only video streams,
with control bus implemented in different framework.
The only concerns I have if we should use Linux bus for that.

Andrzej

>  Tomi
>
>


^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
  2013-10-09 14:08         ` Andrzej Hajda
  (?)
@ 2013-10-11  6:37           ` Tomi Valkeinen
  -1 siblings, 0 replies; 83+ messages in thread
From: Tomi Valkeinen @ 2013-10-11  6:37 UTC (permalink / raw)
  To: Andrzej Hajda, Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

[-- Attachment #1: Type: text/plain, Size: 5336 bytes --]

On 09/10/13 17:08, Andrzej Hajda wrote:

> As I have adopted existing internal driver for MIPI-DSI bus, I did not
> take too much
> care for DT. You are right, 'bta-timeout' is a configuration parameter
> (however its
> minimal value is determined by characteristic of the DSI-slave). On the
> other
> side currently there is no good place for such configuration parameters
> AFAIK.

The minimum bta-timeout should be deducable from the DSI bus speed,
shouldn't it? Thus there's no need to define it anywhere.

>> - enable_hs and enable_te, used to enable/disable HS mode and
>> tearing-elimination
> 
> It seems there should be a way to synchronize TE signal with panel,
> in case signal is provided only to dsi-master. Some callback I suppose?
> Or transfer synchronization should be done by dsi-master.

Hmm, can you explain a bit what you mean?

Do you mean that the panel driver should get a callback when DSI TE
trigger happens?

On OMAP, when using DSI TE trigger, the dsi-master does it all. So the
panel driver just calls update() on the dsi-master, and then the
dsi-master will wait for TE, and then start the transfer. There's also a
callback to the panel driver when the transfer has completed.

>> - set_max_rx_packet_size, used to configure the max rx packet size.
> Similar callbacks should be added to mipi-dsi-bus ops as well, to
> make it complete/generic.

Do you mean the same calls should exist both in the mipi-dbi-bus ops and
on the video ops? If they are called with different values, which one
"wins"?

>> http://article.gmane.org/gmane.comp.video.dri.devel/90651
>> http://article.gmane.org/gmane.comp.video.dri.devel/91269
>> http://article.gmane.org/gmane.comp.video.dri.devel/91272
>>
>> I still think that it's best to consider DSI and DBI as a video bus (not
>> as a separate video bus and a control bus), and provide the packet
>> transfer methods as part of the video ops.
> I have read all posts regarding this issue and currently I tend
> to solution where CDF is used to model only video streams,
> with control bus implemented in different framework.
> The only concerns I have if we should use Linux bus for that.

Ok. I have many other concerns, as I've expressed in the mails =). I
still don't see how it could work. So I'd very much like to see a more
detailed explanation how the separate control & video bus approach would
deal with different scenarios.

Let's consider a DSI-to-HDMI encoder chip. Version A of the chip is
controlled via DSI, version B is controlled via i2c. As the output of
the chip goes to HDMI connector, the DSI bus speed needs to be set
according to the resolution of the HDMI monitor.

So, with version A, the encoder driver would have some kind of pointers
to ctrl_ops and video_ops (or, pointers to dsi_bus instance and
video_bus instance), right? The ctrl_ops would need to have ops like
set_bus_speed, enable_hs, etc, to configure the DSI bus.

When the encoder driver is started, it'd probably set some safe bus
speed, configure the encoder a bit, read the EDID, enable HS,
re-configure the bus speed to match the monitor's video mode, configure
the encoder, and at last enable the video stream.

Version B would have i2c_client and video_ops. When the driver starts,
it'd  probably do the same things as above, except the control messages
would go through i2c. That means that setting the bus speed, enabling
HS, etc, would happen through video_ops, as the i2c side has no
knowledge of the DSI side, right? Would there be identical ops on both
DSI ctrl and video ops?

That sounds very bad. What am I missing here? How would it work?

And, if we want to separate the video and control, I see no reason to
explicitly require the video side to be present. I.e. we could as well
have a DSI peripheral that has only the control bus used. How would that
reflect to, say, the DT presentation? Say, if we have a version A of the
encoder, we could have DT data like this (just a rough example):

soc-dsi {
	encoder {
		input: endpoint {
			remote-endpoint = <&soc-dsi-ep>;
			/* configuration for the DSI lanes */
			dsi-lanes = <0 1 2 3 4 5>;
		};
	};
};

So the encoder would be places inside the SoC's DSI node, similar to how
an i2c device would be placed inside SoC's i2c node. DSI configuration
would be inside the video endpoint data.

Version B would be almost the same:

&i2c0 {
	encoder {
		input: endpoint {
			remote-endpoint = <&soc-dsi-ep>;
			/* configuration for the DSI lanes */
			dsi-lanes = <0 1 2 3 4 5>;
		};
	};
};

Now, how would the video-bus-less device be defined? It'd be inside the
soc-dsi node, that's clear. Where would the DSI lane configuration be?
Not inside 'endpoint' node, as that's for video and wouldn't exist in
this case. Would we have the same lane configuration in two places, once
for video and once for control?

I agree that having DSI/DBI control and video separated would be
elegant. But I'd like to hear what is the technical benefit of that? At
least to me it's clearly more complex to separate them than to keep them
together (to the extent that I don't yet see how it is even possible),
so there must be a good reason for the separation. I don't understand
that reason. What is it?

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
@ 2013-10-11  6:37           ` Tomi Valkeinen
  0 siblings, 0 replies; 83+ messages in thread
From: Tomi Valkeinen @ 2013-10-11  6:37 UTC (permalink / raw)
  To: Andrzej Hajda, Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

[-- Attachment #1: Type: text/plain, Size: 5336 bytes --]

On 09/10/13 17:08, Andrzej Hajda wrote:

> As I have adopted existing internal driver for MIPI-DSI bus, I did not
> take too much
> care for DT. You are right, 'bta-timeout' is a configuration parameter
> (however its
> minimal value is determined by characteristic of the DSI-slave). On the
> other
> side currently there is no good place for such configuration parameters
> AFAIK.

The minimum bta-timeout should be deducable from the DSI bus speed,
shouldn't it? Thus there's no need to define it anywhere.

>> - enable_hs and enable_te, used to enable/disable HS mode and
>> tearing-elimination
> 
> It seems there should be a way to synchronize TE signal with panel,
> in case signal is provided only to dsi-master. Some callback I suppose?
> Or transfer synchronization should be done by dsi-master.

Hmm, can you explain a bit what you mean?

Do you mean that the panel driver should get a callback when DSI TE
trigger happens?

On OMAP, when using DSI TE trigger, the dsi-master does it all. So the
panel driver just calls update() on the dsi-master, and then the
dsi-master will wait for TE, and then start the transfer. There's also a
callback to the panel driver when the transfer has completed.

>> - set_max_rx_packet_size, used to configure the max rx packet size.
> Similar callbacks should be added to mipi-dsi-bus ops as well, to
> make it complete/generic.

Do you mean the same calls should exist both in the mipi-dbi-bus ops and
on the video ops? If they are called with different values, which one
"wins"?

>> http://article.gmane.org/gmane.comp.video.dri.devel/90651
>> http://article.gmane.org/gmane.comp.video.dri.devel/91269
>> http://article.gmane.org/gmane.comp.video.dri.devel/91272
>>
>> I still think that it's best to consider DSI and DBI as a video bus (not
>> as a separate video bus and a control bus), and provide the packet
>> transfer methods as part of the video ops.
> I have read all posts regarding this issue and currently I tend
> to solution where CDF is used to model only video streams,
> with control bus implemented in different framework.
> The only concerns I have if we should use Linux bus for that.

Ok. I have many other concerns, as I've expressed in the mails =). I
still don't see how it could work. So I'd very much like to see a more
detailed explanation how the separate control & video bus approach would
deal with different scenarios.

Let's consider a DSI-to-HDMI encoder chip. Version A of the chip is
controlled via DSI, version B is controlled via i2c. As the output of
the chip goes to HDMI connector, the DSI bus speed needs to be set
according to the resolution of the HDMI monitor.

So, with version A, the encoder driver would have some kind of pointers
to ctrl_ops and video_ops (or, pointers to dsi_bus instance and
video_bus instance), right? The ctrl_ops would need to have ops like
set_bus_speed, enable_hs, etc, to configure the DSI bus.

When the encoder driver is started, it'd probably set some safe bus
speed, configure the encoder a bit, read the EDID, enable HS,
re-configure the bus speed to match the monitor's video mode, configure
the encoder, and at last enable the video stream.

Version B would have i2c_client and video_ops. When the driver starts,
it'd  probably do the same things as above, except the control messages
would go through i2c. That means that setting the bus speed, enabling
HS, etc, would happen through video_ops, as the i2c side has no
knowledge of the DSI side, right? Would there be identical ops on both
DSI ctrl and video ops?

That sounds very bad. What am I missing here? How would it work?

And, if we want to separate the video and control, I see no reason to
explicitly require the video side to be present. I.e. we could as well
have a DSI peripheral that has only the control bus used. How would that
reflect to, say, the DT presentation? Say, if we have a version A of the
encoder, we could have DT data like this (just a rough example):

soc-dsi {
	encoder {
		input: endpoint {
			remote-endpoint = <&soc-dsi-ep>;
			/* configuration for the DSI lanes */
			dsi-lanes = <0 1 2 3 4 5>;
		};
	};
};

So the encoder would be places inside the SoC's DSI node, similar to how
an i2c device would be placed inside SoC's i2c node. DSI configuration
would be inside the video endpoint data.

Version B would be almost the same:

&i2c0 {
	encoder {
		input: endpoint {
			remote-endpoint = <&soc-dsi-ep>;
			/* configuration for the DSI lanes */
			dsi-lanes = <0 1 2 3 4 5>;
		};
	};
};

Now, how would the video-bus-less device be defined? It'd be inside the
soc-dsi node, that's clear. Where would the DSI lane configuration be?
Not inside 'endpoint' node, as that's for video and wouldn't exist in
this case. Would we have the same lane configuration in two places, once
for video and once for control?

I agree that having DSI/DBI control and video separated would be
elegant. But I'd like to hear what is the technical benefit of that? At
least to me it's clearly more complex to separate them than to keep them
together (to the extent that I don't yet see how it is even possible),
so there must be a good reason for the separation. I don't understand
that reason. What is it?

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
@ 2013-10-11  6:37           ` Tomi Valkeinen
  0 siblings, 0 replies; 83+ messages in thread
From: Tomi Valkeinen @ 2013-10-11  6:37 UTC (permalink / raw)
  To: Andrzej Hajda, Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

[-- Attachment #1: Type: text/plain, Size: 5336 bytes --]

On 09/10/13 17:08, Andrzej Hajda wrote:

> As I have adopted existing internal driver for MIPI-DSI bus, I did not
> take too much
> care for DT. You are right, 'bta-timeout' is a configuration parameter
> (however its
> minimal value is determined by characteristic of the DSI-slave). On the
> other
> side currently there is no good place for such configuration parameters
> AFAIK.

The minimum bta-timeout should be deducable from the DSI bus speed,
shouldn't it? Thus there's no need to define it anywhere.

>> - enable_hs and enable_te, used to enable/disable HS mode and
>> tearing-elimination
> 
> It seems there should be a way to synchronize TE signal with panel,
> in case signal is provided only to dsi-master. Some callback I suppose?
> Or transfer synchronization should be done by dsi-master.

Hmm, can you explain a bit what you mean?

Do you mean that the panel driver should get a callback when DSI TE
trigger happens?

On OMAP, when using DSI TE trigger, the dsi-master does it all. So the
panel driver just calls update() on the dsi-master, and then the
dsi-master will wait for TE, and then start the transfer. There's also a
callback to the panel driver when the transfer has completed.

>> - set_max_rx_packet_size, used to configure the max rx packet size.
> Similar callbacks should be added to mipi-dsi-bus ops as well, to
> make it complete/generic.

Do you mean the same calls should exist both in the mipi-dbi-bus ops and
on the video ops? If they are called with different values, which one
"wins"?

>> http://article.gmane.org/gmane.comp.video.dri.devel/90651
>> http://article.gmane.org/gmane.comp.video.dri.devel/91269
>> http://article.gmane.org/gmane.comp.video.dri.devel/91272
>>
>> I still think that it's best to consider DSI and DBI as a video bus (not
>> as a separate video bus and a control bus), and provide the packet
>> transfer methods as part of the video ops.
> I have read all posts regarding this issue and currently I tend
> to solution where CDF is used to model only video streams,
> with control bus implemented in different framework.
> The only concerns I have if we should use Linux bus for that.

Ok. I have many other concerns, as I've expressed in the mails =). I
still don't see how it could work. So I'd very much like to see a more
detailed explanation how the separate control & video bus approach would
deal with different scenarios.

Let's consider a DSI-to-HDMI encoder chip. Version A of the chip is
controlled via DSI, version B is controlled via i2c. As the output of
the chip goes to HDMI connector, the DSI bus speed needs to be set
according to the resolution of the HDMI monitor.

So, with version A, the encoder driver would have some kind of pointers
to ctrl_ops and video_ops (or, pointers to dsi_bus instance and
video_bus instance), right? The ctrl_ops would need to have ops like
set_bus_speed, enable_hs, etc, to configure the DSI bus.

When the encoder driver is started, it'd probably set some safe bus
speed, configure the encoder a bit, read the EDID, enable HS,
re-configure the bus speed to match the monitor's video mode, configure
the encoder, and at last enable the video stream.

Version B would have i2c_client and video_ops. When the driver starts,
it'd  probably do the same things as above, except the control messages
would go through i2c. That means that setting the bus speed, enabling
HS, etc, would happen through video_ops, as the i2c side has no
knowledge of the DSI side, right? Would there be identical ops on both
DSI ctrl and video ops?

That sounds very bad. What am I missing here? How would it work?

And, if we want to separate the video and control, I see no reason to
explicitly require the video side to be present. I.e. we could as well
have a DSI peripheral that has only the control bus used. How would that
reflect to, say, the DT presentation? Say, if we have a version A of the
encoder, we could have DT data like this (just a rough example):

soc-dsi {
	encoder {
		input: endpoint {
			remote-endpoint = <&soc-dsi-ep>;
			/* configuration for the DSI lanes */
			dsi-lanes = <0 1 2 3 4 5>;
		};
	};
};

So the encoder would be places inside the SoC's DSI node, similar to how
an i2c device would be placed inside SoC's i2c node. DSI configuration
would be inside the video endpoint data.

Version B would be almost the same:

&i2c0 {
	encoder {
		input: endpoint {
			remote-endpoint = <&soc-dsi-ep>;
			/* configuration for the DSI lanes */
			dsi-lanes = <0 1 2 3 4 5>;
		};
	};
};

Now, how would the video-bus-less device be defined? It'd be inside the
soc-dsi node, that's clear. Where would the DSI lane configuration be?
Not inside 'endpoint' node, as that's for video and wouldn't exist in
this case. Would we have the same lane configuration in two places, once
for video and once for control?

I agree that having DSI/DBI control and video separated would be
elegant. But I'd like to hear what is the technical benefit of that? At
least to me it's clearly more complex to separate them than to keep them
together (to the extent that I don't yet see how it is even possible),
so there must be a good reason for the separation. I don't understand
that reason. What is it?

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
  2013-10-11  6:37           ` Tomi Valkeinen
@ 2013-10-11 11:19             ` Andrzej Hajda
  -1 siblings, 0 replies; 83+ messages in thread
From: Andrzej Hajda @ 2013-10-11 11:19 UTC (permalink / raw)
  To: Tomi Valkeinen, Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

On 10/11/2013 08:37 AM, Tomi Valkeinen wrote:
> On 09/10/13 17:08, Andrzej Hajda wrote:
>
>> As I have adopted existing internal driver for MIPI-DSI bus, I did not
>> take too much
>> care for DT. You are right, 'bta-timeout' is a configuration parameter
>> (however its
>> minimal value is determined by characteristic of the DSI-slave). On the
>> other
>> side currently there is no good place for such configuration parameters
>> AFAIK.
> The minimum bta-timeout should be deducable from the DSI bus speed,
> shouldn't it? Thus there's no need to define it anywhere.
Hmm, specification says "This specified period shall be longer then
the maximum possible turnaround delay for the unit to which the
turnaround request was sent".
>
>>> - enable_hs and enable_te, used to enable/disable HS mode and
>>> tearing-elimination
>> It seems there should be a way to synchronize TE signal with panel,
>> in case signal is provided only to dsi-master. Some callback I suppose?
>> Or transfer synchronization should be done by dsi-master.
> Hmm, can you explain a bit what you mean?
>
> Do you mean that the panel driver should get a callback when DSI TE
> trigger happens?
>
> On OMAP, when using DSI TE trigger, the dsi-master does it all. So the
> panel driver just calls update() on the dsi-master, and then the
> dsi-master will wait for TE, and then start the transfer. There's also a
> callback to the panel driver when the transfer has completed.
Yes I though about a callback, but approach with DSI-master taking care
of synchronization in fact better fits to exynos-dsi and I suspect to
omap also.
>
>>> - set_max_rx_packet_size, used to configure the max rx packet size.
>> Similar callbacks should be added to mipi-dsi-bus ops as well, to
>> make it complete/generic.
> Do you mean the same calls should exist both in the mipi-dbi-bus ops and
> on the video ops? If they are called with different values, which one
> "wins"?
No, I meant that if mipi-dbi-bus want to be complete it should have
similar ops.
I did not think about scenario with two overlaping APIs.
>
>>> http://article.gmane.org/gmane.comp.video.dri.devel/90651
>>> http://article.gmane.org/gmane.comp.video.dri.devel/91269
>>> http://article.gmane.org/gmane.comp.video.dri.devel/91272
>>>
>>> I still think that it's best to consider DSI and DBI as a video bus (not
>>> as a separate video bus and a control bus), and provide the packet
>>> transfer methods as part of the video ops.
>> I have read all posts regarding this issue and currently I tend
>> to solution where CDF is used to model only video streams,
>> with control bus implemented in different framework.
>> The only concerns I have if we should use Linux bus for that.
> Ok. I have many other concerns, as I've expressed in the mails =). I
> still don't see how it could work. So I'd very much like to see a more
> detailed explanation how the separate control & video bus approach would
> deal with different scenarios.
>
> Let's consider a DSI-to-HDMI encoder chip. Version A of the chip is
> controlled via DSI, version B is controlled via i2c. As the output of
> the chip goes to HDMI connector, the DSI bus speed needs to be set
> according to the resolution of the HDMI monitor.
>
> So, with version A, the encoder driver would have some kind of pointers
> to ctrl_ops and video_ops (or, pointers to dsi_bus instance and
> video_bus instance), right? The ctrl_ops would need to have ops like
> set_bus_speed, enable_hs, etc, to configure the DSI bus.
>
> When the encoder driver is started, it'd probably set some safe bus
> speed, configure the encoder a bit, read the EDID, enable HS,
> re-configure the bus speed to match the monitor's video mode, configure
> the encoder, and at last enable the video stream.
>
> Version B would have i2c_client and video_ops. When the driver starts,
> it'd  probably do the same things as above, except the control messages
> would go through i2c. That means that setting the bus speed, enabling
> HS, etc, would happen through video_ops, as the i2c side has no
> knowledge of the DSI side, right? Would there be identical ops on both
> DSI ctrl and video ops?
>
> That sounds very bad. What am I missing here? How would it work?
If I undrestand correctly you think about CDF topology like below:

DispContr(SoC) ---> DSI-master(SoC) ---> encoder(DSI or I2C)

But I think with mipi-dsi-bus topology could look like:

DispContr(SoC) ---> encoder(DSI or I2C)

DSI-master will not have its own entity, in the graph it could be
represented
by the link(--->), as it really does not process the video, only
transports it.

In case of version A I think everything is clear.
In case of version B it does not seems so nice at the first sight, but
still seems quite straightforward to me - special plink in encoder's
node pointing
to DSI-master, driver will find the device in runtime and use ops as needed
(additional ops/helpers required).
This is also the way to support devices which can be controlled by DSI
and I2C
in the same time. Anyway I suspect such scenario will be quite rare.

>
> And, if we want to separate the video and control, I see no reason to
> explicitly require the video side to be present. I.e. we could as well
> have a DSI peripheral that has only the control bus used. How would that
> reflect to, say, the DT presentation? Say, if we have a version A of the
> encoder, we could have DT data like this (just a rough example):
>
> soc-dsi {
> 	encoder {
> 		input: endpoint {
> 			remote-endpoint = <&soc-dsi-ep>;
Here I would replace &soc-dsi-ep by phandle to display controller/crtc/....

> 			/* configuration for the DSI lanes */
> 			dsi-lanes = <0 1 2 3 4 5>;
Wow, quite advanced DSI.
> 		};
> 	};
> };
>
> So the encoder would be places inside the SoC's DSI node, similar to how
> an i2c device would be placed inside SoC's i2c node. DSI configuration
> would be inside the video endpoint data.
>
> Version B would be almost the same:
>
> &i2c0 {
> 	encoder {
> 		input: endpoint {
> 			remote-endpoint = <&soc-dsi-ep>;
&soc-dsi-ep => &disp-ctrl-ep
> 			/* configuration for the DSI lanes */
> 			dsi-lanes = <0 1 2 3 4 5>;
> 		};
> 	};
> };
>
> Now, how would the video-bus-less device be defined?
> It'd be inside the
> soc-dsi node, that's clear. Where would the DSI lane configuration be?
> Not inside 'endpoint' node, as that's for video and wouldn't exist in
> this case. Would we have the same lane configuration in two places, once
> for video and once for control?
I think it is control setting, so it should be put outside endpoint node.
Probably it could be placed in encoder node.
>
> I agree that having DSI/DBI control and video separated would be
> elegant. But I'd like to hear what is the technical benefit of that? At
> least to me it's clearly more complex to separate them than to keep them
> together (to the extent that I don't yet see how it is even possible),
> so there must be a good reason for the separation. I don't understand
> that reason. What is it?
Roughly speaking it is a question where is the more convenient place to
put bunch
of opses, technically both solutions can be somehow implemented.

Pros of mipi bus:
- no fake entity in CDF, with fake opses, I have to use similar entities
in MIPI-CSI
camera pipelines and it complicates life without any benefit(at least
from user side),
- CDF models only video buses, control bus is a domain of Linux buses,
- less platform_bus abusing,
- better device tree topology (at least for common cases),
- quite simple in case of typical devices.

Regards
Andrzej
>
>  Tomi
>
>


^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
@ 2013-10-11 11:19             ` Andrzej Hajda
  0 siblings, 0 replies; 83+ messages in thread
From: Andrzej Hajda @ 2013-10-11 11:19 UTC (permalink / raw)
  To: Tomi Valkeinen, Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

On 10/11/2013 08:37 AM, Tomi Valkeinen wrote:
> On 09/10/13 17:08, Andrzej Hajda wrote:
>
>> As I have adopted existing internal driver for MIPI-DSI bus, I did not
>> take too much
>> care for DT. You are right, 'bta-timeout' is a configuration parameter
>> (however its
>> minimal value is determined by characteristic of the DSI-slave). On the
>> other
>> side currently there is no good place for such configuration parameters
>> AFAIK.
> The minimum bta-timeout should be deducable from the DSI bus speed,
> shouldn't it? Thus there's no need to define it anywhere.
Hmm, specification says "This specified period shall be longer then
the maximum possible turnaround delay for the unit to which the
turnaround request was sent".
>
>>> - enable_hs and enable_te, used to enable/disable HS mode and
>>> tearing-elimination
>> It seems there should be a way to synchronize TE signal with panel,
>> in case signal is provided only to dsi-master. Some callback I suppose?
>> Or transfer synchronization should be done by dsi-master.
> Hmm, can you explain a bit what you mean?
>
> Do you mean that the panel driver should get a callback when DSI TE
> trigger happens?
>
> On OMAP, when using DSI TE trigger, the dsi-master does it all. So the
> panel driver just calls update() on the dsi-master, and then the
> dsi-master will wait for TE, and then start the transfer. There's also a
> callback to the panel driver when the transfer has completed.
Yes I though about a callback, but approach with DSI-master taking care
of synchronization in fact better fits to exynos-dsi and I suspect to
omap also.
>
>>> - set_max_rx_packet_size, used to configure the max rx packet size.
>> Similar callbacks should be added to mipi-dsi-bus ops as well, to
>> make it complete/generic.
> Do you mean the same calls should exist both in the mipi-dbi-bus ops and
> on the video ops? If they are called with different values, which one
> "wins"?
No, I meant that if mipi-dbi-bus want to be complete it should have
similar ops.
I did not think about scenario with two overlaping APIs.
>
>>> http://article.gmane.org/gmane.comp.video.dri.devel/90651
>>> http://article.gmane.org/gmane.comp.video.dri.devel/91269
>>> http://article.gmane.org/gmane.comp.video.dri.devel/91272
>>>
>>> I still think that it's best to consider DSI and DBI as a video bus (not
>>> as a separate video bus and a control bus), and provide the packet
>>> transfer methods as part of the video ops.
>> I have read all posts regarding this issue and currently I tend
>> to solution where CDF is used to model only video streams,
>> with control bus implemented in different framework.
>> The only concerns I have if we should use Linux bus for that.
> Ok. I have many other concerns, as I've expressed in the mails =). I
> still don't see how it could work. So I'd very much like to see a more
> detailed explanation how the separate control & video bus approach would
> deal with different scenarios.
>
> Let's consider a DSI-to-HDMI encoder chip. Version A of the chip is
> controlled via DSI, version B is controlled via i2c. As the output of
> the chip goes to HDMI connector, the DSI bus speed needs to be set
> according to the resolution of the HDMI monitor.
>
> So, with version A, the encoder driver would have some kind of pointers
> to ctrl_ops and video_ops (or, pointers to dsi_bus instance and
> video_bus instance), right? The ctrl_ops would need to have ops like
> set_bus_speed, enable_hs, etc, to configure the DSI bus.
>
> When the encoder driver is started, it'd probably set some safe bus
> speed, configure the encoder a bit, read the EDID, enable HS,
> re-configure the bus speed to match the monitor's video mode, configure
> the encoder, and at last enable the video stream.
>
> Version B would have i2c_client and video_ops. When the driver starts,
> it'd  probably do the same things as above, except the control messages
> would go through i2c. That means that setting the bus speed, enabling
> HS, etc, would happen through video_ops, as the i2c side has no
> knowledge of the DSI side, right? Would there be identical ops on both
> DSI ctrl and video ops?
>
> That sounds very bad. What am I missing here? How would it work?
If I undrestand correctly you think about CDF topology like below:

DispContr(SoC) ---> DSI-master(SoC) ---> encoder(DSI or I2C)

But I think with mipi-dsi-bus topology could look like:

DispContr(SoC) ---> encoder(DSI or I2C)

DSI-master will not have its own entity, in the graph it could be
represented
by the link(--->), as it really does not process the video, only
transports it.

In case of version A I think everything is clear.
In case of version B it does not seems so nice at the first sight, but
still seems quite straightforward to me - special plink in encoder's
node pointing
to DSI-master, driver will find the device in runtime and use ops as needed
(additional ops/helpers required).
This is also the way to support devices which can be controlled by DSI
and I2C
in the same time. Anyway I suspect such scenario will be quite rare.

>
> And, if we want to separate the video and control, I see no reason to
> explicitly require the video side to be present. I.e. we could as well
> have a DSI peripheral that has only the control bus used. How would that
> reflect to, say, the DT presentation? Say, if we have a version A of the
> encoder, we could have DT data like this (just a rough example):
>
> soc-dsi {
> 	encoder {
> 		input: endpoint {
> 			remote-endpoint = <&soc-dsi-ep>;
Here I would replace &soc-dsi-ep by phandle to display controller/crtc/....

> 			/* configuration for the DSI lanes */
> 			dsi-lanes = <0 1 2 3 4 5>;
Wow, quite advanced DSI.
> 		};
> 	};
> };
>
> So the encoder would be places inside the SoC's DSI node, similar to how
> an i2c device would be placed inside SoC's i2c node. DSI configuration
> would be inside the video endpoint data.
>
> Version B would be almost the same:
>
> &i2c0 {
> 	encoder {
> 		input: endpoint {
> 			remote-endpoint = <&soc-dsi-ep>;
&soc-dsi-ep => &disp-ctrl-ep
> 			/* configuration for the DSI lanes */
> 			dsi-lanes = <0 1 2 3 4 5>;
> 		};
> 	};
> };
>
> Now, how would the video-bus-less device be defined?
> It'd be inside the
> soc-dsi node, that's clear. Where would the DSI lane configuration be?
> Not inside 'endpoint' node, as that's for video and wouldn't exist in
> this case. Would we have the same lane configuration in two places, once
> for video and once for control?
I think it is control setting, so it should be put outside endpoint node.
Probably it could be placed in encoder node.
>
> I agree that having DSI/DBI control and video separated would be
> elegant. But I'd like to hear what is the technical benefit of that? At
> least to me it's clearly more complex to separate them than to keep them
> together (to the extent that I don't yet see how it is even possible),
> so there must be a good reason for the separation. I don't understand
> that reason. What is it?
Roughly speaking it is a question where is the more convenient place to
put bunch
of opses, technically both solutions can be somehow implemented.

Pros of mipi bus:
- no fake entity in CDF, with fake opses, I have to use similar entities
in MIPI-CSI
camera pipelines and it complicates life without any benefit(at least
from user side),
- CDF models only video buses, control bus is a domain of Linux buses,
- less platform_bus abusing,
- better device tree topology (at least for common cases),
- quite simple in case of typical devices.

Regards
Andrzej
>
>  Tomi
>
>


^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
  2013-10-11 11:19             ` Andrzej Hajda
  (?)
@ 2013-10-11 12:30               ` Tomi Valkeinen
  -1 siblings, 0 replies; 83+ messages in thread
From: Tomi Valkeinen @ 2013-10-11 12:30 UTC (permalink / raw)
  To: Andrzej Hajda, Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

[-- Attachment #1: Type: text/plain, Size: 7199 bytes --]

On 11/10/13 14:19, Andrzej Hajda wrote:
> On 10/11/2013 08:37 AM, Tomi Valkeinen wrote:

>> The minimum bta-timeout should be deducable from the DSI bus speed,
>> shouldn't it? Thus there's no need to define it anywhere.
> Hmm, specification says "This specified period shall be longer then
> the maximum possible turnaround delay for the unit to which the
> turnaround request was sent".

Ah, you're right. We can't know how long the peripheral will take
responding. I was thinking of something that only depends on the
bus-speed and the timings for that.

> If I undrestand correctly you think about CDF topology like below:
> 
> DispContr(SoC) ---> DSI-master(SoC) ---> encoder(DSI or I2C)
> 
> But I think with mipi-dsi-bus topology could look like:
> 
> DispContr(SoC) ---> encoder(DSI or I2C)
> 
> DSI-master will not have its own entity, in the graph it could be
> represented
> by the link(--->), as it really does not process the video, only
> transports it.

At least in OMAP, the SoC's DSI-master receives parallel RGB data from
DISPC, and encodes it to DSI. Isn't that processing? It's basically a
DPI-to-DSI encoder. And it's not a simple pass-through, the DSI video
timings could be considerably different than the DPI timings.

> In case of version A I think everything is clear.
> In case of version B it does not seems so nice at the first sight, but
> still seems quite straightforward to me - special plink in encoder's
> node pointing
> to DSI-master, driver will find the device in runtime and use ops as needed
> (additional ops/helpers required).
> This is also the way to support devices which can be controlled by DSI
> and I2C
> in the same time. Anyway I suspect such scenario will be quite rare.

Okay, so if I gather it right, you say there would be something like
'dsi_adapter' (like i2c_adapter), which represents the dsi-master. And a
driver could get pointer to this, regardless of whether it the linux
device is a DSI device.

At least one issue with this approach is the endpoint problem (see below).

>> And, if we want to separate the video and control, I see no reason to
>> explicitly require the video side to be present. I.e. we could as well
>> have a DSI peripheral that has only the control bus used. How would that
>> reflect to, say, the DT presentation? Say, if we have a version A of the
>> encoder, we could have DT data like this (just a rough example):
>>
>> soc-dsi {
>> 	encoder {
>> 		input: endpoint {
>> 			remote-endpoint = <&soc-dsi-ep>;
> Here I would replace &soc-dsi-ep by phandle to display controller/crtc/....
> 
>> 			/* configuration for the DSI lanes */
>> 			dsi-lanes = <0 1 2 3 4 5>;
> Wow, quite advanced DSI.

Wha? That just means there is one clock lane and two datalanes, nothing
more =). We can select the polarity of a lane, so we describe both the
positive and negative lines there. So it says clk- is connected to pin
0, clk+ connected to pin 1, etc.

>> 		};
>> 	};
>> };
>>
>> So the encoder would be places inside the SoC's DSI node, similar to how
>> an i2c device would be placed inside SoC's i2c node. DSI configuration
>> would be inside the video endpoint data.
>>
>> Version B would be almost the same:
>>
>> &i2c0 {
>> 	encoder {
>> 		input: endpoint {
>> 			remote-endpoint = <&soc-dsi-ep>;
> &soc-dsi-ep => &disp-ctrl-ep
>> 			/* configuration for the DSI lanes */
>> 			dsi-lanes = <0 1 2 3 4 5>;
>> 		};
>> 	};
>> };
>>
>> Now, how would the video-bus-less device be defined?
>> It'd be inside the
>> soc-dsi node, that's clear. Where would the DSI lane configuration be?
>> Not inside 'endpoint' node, as that's for video and wouldn't exist in
>> this case. Would we have the same lane configuration in two places, once
>> for video and once for control?
> I think it is control setting, so it should be put outside endpoint node.
> Probably it could be placed in encoder node.

Well, one point of the endpoints is also to allow "switching" of video
devices.

For example, I could have a board with a SoC's DSI output, connected to
two DSI panels. There would be some kind of mux between, so that I can
select which of the panels is actually connected to the SoC.

Here the first panel could use 2 datalanes, the second one 4. Thus, the
DSI master would have two endpoints, the other one using 2 and the other
4 datalanes.

If we decide that kind of support is not needed, well, is there even
need for the V4L2 endpoints in the DT data at all?

>> I agree that having DSI/DBI control and video separated would be
>> elegant. But I'd like to hear what is the technical benefit of that? At
>> least to me it's clearly more complex to separate them than to keep them
>> together (to the extent that I don't yet see how it is even possible),
>> so there must be a good reason for the separation. I don't understand
>> that reason. What is it?
> Roughly speaking it is a question where is the more convenient place to
> put bunch
> of opses, technically both solutions can be somehow implemented.

Well, it's also about dividing a single physical bus into two separate
interfaces to it. It sounds to me that it would be much more complex
with locking. With a single API, we can just say "the caller handles
locking". With two separate interfaces, there must be locking at the
lower level.

> Pros of mipi bus:
> - no fake entity in CDF, with fake opses, I have to use similar entities
> in MIPI-CSI
> camera pipelines and it complicates life without any benefit(at least
> from user side),

You mean the DSI-master? I don't see how it's "fake", it's a video
processing unit that has to be configured. Even if we forget the control
side, and just think about plain video stream with DSI video mode,
there's are things to configure with it.

What kind of issues you have in the CSI side, then?

> - CDF models only video buses, control bus is a domain of Linux buses,

Yes, but in this case the buses are the same. It makes me a bit nervous
to have two separate ways (video and control) to use the same bus, in a
case like video where timing is critical.

So yes, we can consider video and control buses as "virtual" buses, and
the actual transport is the DSI bus. Maybe it can be done. It just makes
me a bit nervous =).

> - less platform_bus abusing,

Well, platform.txt says

"This pseudo-bus
is used to connect devices on busses with minimal infrastructure,
like those used to integrate peripherals on many system-on-chip
processors, or some "legacy" PC interconnects; as opposed to large
formally specified ones like PCI or USB."

I don't think DSI and DBI as platform bus is that far from the
description. They are "simple", no probing point-to-point (in practice)
buses. There's not much "bus" to speak of, just a point-to-point link.

> - better device tree topology (at least for common cases),

Even if we use platform devices for DSI peripherals, we can have them
described under the DSI master node.

> - quite simple in case of typical devices.

Still more complex than single API for both video and control =).

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
@ 2013-10-11 12:30               ` Tomi Valkeinen
  0 siblings, 0 replies; 83+ messages in thread
From: Tomi Valkeinen @ 2013-10-11 12:30 UTC (permalink / raw)
  To: Andrzej Hajda, Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

[-- Attachment #1: Type: text/plain, Size: 7199 bytes --]

On 11/10/13 14:19, Andrzej Hajda wrote:
> On 10/11/2013 08:37 AM, Tomi Valkeinen wrote:

>> The minimum bta-timeout should be deducable from the DSI bus speed,
>> shouldn't it? Thus there's no need to define it anywhere.
> Hmm, specification says "This specified period shall be longer then
> the maximum possible turnaround delay for the unit to which the
> turnaround request was sent".

Ah, you're right. We can't know how long the peripheral will take
responding. I was thinking of something that only depends on the
bus-speed and the timings for that.

> If I undrestand correctly you think about CDF topology like below:
> 
> DispContr(SoC) ---> DSI-master(SoC) ---> encoder(DSI or I2C)
> 
> But I think with mipi-dsi-bus topology could look like:
> 
> DispContr(SoC) ---> encoder(DSI or I2C)
> 
> DSI-master will not have its own entity, in the graph it could be
> represented
> by the link(--->), as it really does not process the video, only
> transports it.

At least in OMAP, the SoC's DSI-master receives parallel RGB data from
DISPC, and encodes it to DSI. Isn't that processing? It's basically a
DPI-to-DSI encoder. And it's not a simple pass-through, the DSI video
timings could be considerably different than the DPI timings.

> In case of version A I think everything is clear.
> In case of version B it does not seems so nice at the first sight, but
> still seems quite straightforward to me - special plink in encoder's
> node pointing
> to DSI-master, driver will find the device in runtime and use ops as needed
> (additional ops/helpers required).
> This is also the way to support devices which can be controlled by DSI
> and I2C
> in the same time. Anyway I suspect such scenario will be quite rare.

Okay, so if I gather it right, you say there would be something like
'dsi_adapter' (like i2c_adapter), which represents the dsi-master. And a
driver could get pointer to this, regardless of whether it the linux
device is a DSI device.

At least one issue with this approach is the endpoint problem (see below).

>> And, if we want to separate the video and control, I see no reason to
>> explicitly require the video side to be present. I.e. we could as well
>> have a DSI peripheral that has only the control bus used. How would that
>> reflect to, say, the DT presentation? Say, if we have a version A of the
>> encoder, we could have DT data like this (just a rough example):
>>
>> soc-dsi {
>> 	encoder {
>> 		input: endpoint {
>> 			remote-endpoint = <&soc-dsi-ep>;
> Here I would replace &soc-dsi-ep by phandle to display controller/crtc/....
> 
>> 			/* configuration for the DSI lanes */
>> 			dsi-lanes = <0 1 2 3 4 5>;
> Wow, quite advanced DSI.

Wha? That just means there is one clock lane and two datalanes, nothing
more =). We can select the polarity of a lane, so we describe both the
positive and negative lines there. So it says clk- is connected to pin
0, clk+ connected to pin 1, etc.

>> 		};
>> 	};
>> };
>>
>> So the encoder would be places inside the SoC's DSI node, similar to how
>> an i2c device would be placed inside SoC's i2c node. DSI configuration
>> would be inside the video endpoint data.
>>
>> Version B would be almost the same:
>>
>> &i2c0 {
>> 	encoder {
>> 		input: endpoint {
>> 			remote-endpoint = <&soc-dsi-ep>;
> &soc-dsi-ep => &disp-ctrl-ep
>> 			/* configuration for the DSI lanes */
>> 			dsi-lanes = <0 1 2 3 4 5>;
>> 		};
>> 	};
>> };
>>
>> Now, how would the video-bus-less device be defined?
>> It'd be inside the
>> soc-dsi node, that's clear. Where would the DSI lane configuration be?
>> Not inside 'endpoint' node, as that's for video and wouldn't exist in
>> this case. Would we have the same lane configuration in two places, once
>> for video and once for control?
> I think it is control setting, so it should be put outside endpoint node.
> Probably it could be placed in encoder node.

Well, one point of the endpoints is also to allow "switching" of video
devices.

For example, I could have a board with a SoC's DSI output, connected to
two DSI panels. There would be some kind of mux between, so that I can
select which of the panels is actually connected to the SoC.

Here the first panel could use 2 datalanes, the second one 4. Thus, the
DSI master would have two endpoints, the other one using 2 and the other
4 datalanes.

If we decide that kind of support is not needed, well, is there even
need for the V4L2 endpoints in the DT data at all?

>> I agree that having DSI/DBI control and video separated would be
>> elegant. But I'd like to hear what is the technical benefit of that? At
>> least to me it's clearly more complex to separate them than to keep them
>> together (to the extent that I don't yet see how it is even possible),
>> so there must be a good reason for the separation. I don't understand
>> that reason. What is it?
> Roughly speaking it is a question where is the more convenient place to
> put bunch
> of opses, technically both solutions can be somehow implemented.

Well, it's also about dividing a single physical bus into two separate
interfaces to it. It sounds to me that it would be much more complex
with locking. With a single API, we can just say "the caller handles
locking". With two separate interfaces, there must be locking at the
lower level.

> Pros of mipi bus:
> - no fake entity in CDF, with fake opses, I have to use similar entities
> in MIPI-CSI
> camera pipelines and it complicates life without any benefit(at least
> from user side),

You mean the DSI-master? I don't see how it's "fake", it's a video
processing unit that has to be configured. Even if we forget the control
side, and just think about plain video stream with DSI video mode,
there's are things to configure with it.

What kind of issues you have in the CSI side, then?

> - CDF models only video buses, control bus is a domain of Linux buses,

Yes, but in this case the buses are the same. It makes me a bit nervous
to have two separate ways (video and control) to use the same bus, in a
case like video where timing is critical.

So yes, we can consider video and control buses as "virtual" buses, and
the actual transport is the DSI bus. Maybe it can be done. It just makes
me a bit nervous =).

> - less platform_bus abusing,

Well, platform.txt says

"This pseudo-bus
is used to connect devices on busses with minimal infrastructure,
like those used to integrate peripherals on many system-on-chip
processors, or some "legacy" PC interconnects; as opposed to large
formally specified ones like PCI or USB."

I don't think DSI and DBI as platform bus is that far from the
description. They are "simple", no probing point-to-point (in practice)
buses. There's not much "bus" to speak of, just a point-to-point link.

> - better device tree topology (at least for common cases),

Even if we use platform devices for DSI peripherals, we can have them
described under the DSI master node.

> - quite simple in case of typical devices.

Still more complex than single API for both video and control =).

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
@ 2013-10-11 12:30               ` Tomi Valkeinen
  0 siblings, 0 replies; 83+ messages in thread
From: Tomi Valkeinen @ 2013-10-11 12:30 UTC (permalink / raw)
  To: Andrzej Hajda, Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

[-- Attachment #1: Type: text/plain, Size: 7199 bytes --]

On 11/10/13 14:19, Andrzej Hajda wrote:
> On 10/11/2013 08:37 AM, Tomi Valkeinen wrote:

>> The minimum bta-timeout should be deducable from the DSI bus speed,
>> shouldn't it? Thus there's no need to define it anywhere.
> Hmm, specification says "This specified period shall be longer then
> the maximum possible turnaround delay for the unit to which the
> turnaround request was sent".

Ah, you're right. We can't know how long the peripheral will take
responding. I was thinking of something that only depends on the
bus-speed and the timings for that.

> If I undrestand correctly you think about CDF topology like below:
> 
> DispContr(SoC) ---> DSI-master(SoC) ---> encoder(DSI or I2C)
> 
> But I think with mipi-dsi-bus topology could look like:
> 
> DispContr(SoC) ---> encoder(DSI or I2C)
> 
> DSI-master will not have its own entity, in the graph it could be
> represented
> by the link(--->), as it really does not process the video, only
> transports it.

At least in OMAP, the SoC's DSI-master receives parallel RGB data from
DISPC, and encodes it to DSI. Isn't that processing? It's basically a
DPI-to-DSI encoder. And it's not a simple pass-through, the DSI video
timings could be considerably different than the DPI timings.

> In case of version A I think everything is clear.
> In case of version B it does not seems so nice at the first sight, but
> still seems quite straightforward to me - special plink in encoder's
> node pointing
> to DSI-master, driver will find the device in runtime and use ops as needed
> (additional ops/helpers required).
> This is also the way to support devices which can be controlled by DSI
> and I2C
> in the same time. Anyway I suspect such scenario will be quite rare.

Okay, so if I gather it right, you say there would be something like
'dsi_adapter' (like i2c_adapter), which represents the dsi-master. And a
driver could get pointer to this, regardless of whether it the linux
device is a DSI device.

At least one issue with this approach is the endpoint problem (see below).

>> And, if we want to separate the video and control, I see no reason to
>> explicitly require the video side to be present. I.e. we could as well
>> have a DSI peripheral that has only the control bus used. How would that
>> reflect to, say, the DT presentation? Say, if we have a version A of the
>> encoder, we could have DT data like this (just a rough example):
>>
>> soc-dsi {
>> 	encoder {
>> 		input: endpoint {
>> 			remote-endpoint = <&soc-dsi-ep>;
> Here I would replace &soc-dsi-ep by phandle to display controller/crtc/....
> 
>> 			/* configuration for the DSI lanes */
>> 			dsi-lanes = <0 1 2 3 4 5>;
> Wow, quite advanced DSI.

Wha? That just means there is one clock lane and two datalanes, nothing
more =). We can select the polarity of a lane, so we describe both the
positive and negative lines there. So it says clk- is connected to pin
0, clk+ connected to pin 1, etc.

>> 		};
>> 	};
>> };
>>
>> So the encoder would be places inside the SoC's DSI node, similar to how
>> an i2c device would be placed inside SoC's i2c node. DSI configuration
>> would be inside the video endpoint data.
>>
>> Version B would be almost the same:
>>
>> &i2c0 {
>> 	encoder {
>> 		input: endpoint {
>> 			remote-endpoint = <&soc-dsi-ep>;
> &soc-dsi-ep => &disp-ctrl-ep
>> 			/* configuration for the DSI lanes */
>> 			dsi-lanes = <0 1 2 3 4 5>;
>> 		};
>> 	};
>> };
>>
>> Now, how would the video-bus-less device be defined?
>> It'd be inside the
>> soc-dsi node, that's clear. Where would the DSI lane configuration be?
>> Not inside 'endpoint' node, as that's for video and wouldn't exist in
>> this case. Would we have the same lane configuration in two places, once
>> for video and once for control?
> I think it is control setting, so it should be put outside endpoint node.
> Probably it could be placed in encoder node.

Well, one point of the endpoints is also to allow "switching" of video
devices.

For example, I could have a board with a SoC's DSI output, connected to
two DSI panels. There would be some kind of mux between, so that I can
select which of the panels is actually connected to the SoC.

Here the first panel could use 2 datalanes, the second one 4. Thus, the
DSI master would have two endpoints, the other one using 2 and the other
4 datalanes.

If we decide that kind of support is not needed, well, is there even
need for the V4L2 endpoints in the DT data at all?

>> I agree that having DSI/DBI control and video separated would be
>> elegant. But I'd like to hear what is the technical benefit of that? At
>> least to me it's clearly more complex to separate them than to keep them
>> together (to the extent that I don't yet see how it is even possible),
>> so there must be a good reason for the separation. I don't understand
>> that reason. What is it?
> Roughly speaking it is a question where is the more convenient place to
> put bunch
> of opses, technically both solutions can be somehow implemented.

Well, it's also about dividing a single physical bus into two separate
interfaces to it. It sounds to me that it would be much more complex
with locking. With a single API, we can just say "the caller handles
locking". With two separate interfaces, there must be locking at the
lower level.

> Pros of mipi bus:
> - no fake entity in CDF, with fake opses, I have to use similar entities
> in MIPI-CSI
> camera pipelines and it complicates life without any benefit(at least
> from user side),

You mean the DSI-master? I don't see how it's "fake", it's a video
processing unit that has to be configured. Even if we forget the control
side, and just think about plain video stream with DSI video mode,
there's are things to configure with it.

What kind of issues you have in the CSI side, then?

> - CDF models only video buses, control bus is a domain of Linux buses,

Yes, but in this case the buses are the same. It makes me a bit nervous
to have two separate ways (video and control) to use the same bus, in a
case like video where timing is critical.

So yes, we can consider video and control buses as "virtual" buses, and
the actual transport is the DSI bus. Maybe it can be done. It just makes
me a bit nervous =).

> - less platform_bus abusing,

Well, platform.txt says

"This pseudo-bus
is used to connect devices on busses with minimal infrastructure,
like those used to integrate peripherals on many system-on-chip
processors, or some "legacy" PC interconnects; as opposed to large
formally specified ones like PCI or USB."

I don't think DSI and DBI as platform bus is that far from the
description. They are "simple", no probing point-to-point (in practice)
buses. There's not much "bus" to speak of, just a point-to-point link.

> - better device tree topology (at least for common cases),

Even if we use platform devices for DSI peripherals, we can have them
described under the DSI master node.

> - quite simple in case of typical devices.

Still more complex than single API for both video and control =).

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
  2013-10-11 12:30               ` Tomi Valkeinen
@ 2013-10-11 14:16                 ` Andrzej Hajda
  -1 siblings, 0 replies; 83+ messages in thread
From: Andrzej Hajda @ 2013-10-11 14:16 UTC (permalink / raw)
  To: Tomi Valkeinen, Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

On 10/11/2013 02:30 PM, Tomi Valkeinen wrote:
> On 11/10/13 14:19, Andrzej Hajda wrote:
>> On 10/11/2013 08:37 AM, Tomi Valkeinen wrote:
>>> The minimum bta-timeout should be deducable from the DSI bus speed,
>>> shouldn't it? Thus there's no need to define it anywhere.
>> Hmm, specification says "This specified period shall be longer then
>> the maximum possible turnaround delay for the unit to which the
>> turnaround request was sent".
> Ah, you're right. We can't know how long the peripheral will take
> responding. I was thinking of something that only depends on the
> bus-speed and the timings for that.
>
>> If I undrestand correctly you think about CDF topology like below:
>>
>> DispContr(SoC) ---> DSI-master(SoC) ---> encoder(DSI or I2C)
>>
>> But I think with mipi-dsi-bus topology could look like:
>>
>> DispContr(SoC) ---> encoder(DSI or I2C)
>>
>> DSI-master will not have its own entity, in the graph it could be
>> represented
>> by the link(--->), as it really does not process the video, only
>> transports it.
> At least in OMAP, the SoC's DSI-master receives parallel RGB data from
> DISPC, and encodes it to DSI. Isn't that processing? It's basically a
> DPI-to-DSI encoder. And it's not a simple pass-through, the DSI video
> timings could be considerably different than the DPI timings.
Picture size, content and format is the same on input and on output of DSI.
The same bits which enters DSI appears on the output. Internally bits
order can
be different but practically you are configuring DSI master and slave
with the same format.

If you create DSI entity you will have to always set the same format and
size on DSI input, DSI output and encoder input.
If you skip creating DSI entity you loose nothing, and you do not need
to take care of it.

>
>> In case of version A I think everything is clear.
>> In case of version B it does not seems so nice at the first sight, but
>> still seems quite straightforward to me - special plink in encoder's
>> node pointing
>> to DSI-master, driver will find the device in runtime and use ops as needed
>> (additional ops/helpers required).
>> This is also the way to support devices which can be controlled by DSI
>> and I2C
>> in the same time. Anyway I suspect such scenario will be quite rare.
> Okay, so if I gather it right, you say there would be something like
> 'dsi_adapter' (like i2c_adapter), which represents the dsi-master. And a
> driver could get pointer to this, regardless of whether it the linux
> device is a DSI device.
>
> At least one issue with this approach is the endpoint problem (see below).
>
>>> And, if we want to separate the video and control, I see no reason to
>>> explicitly require the video side to be present. I.e. we could as well
>>> have a DSI peripheral that has only the control bus used. How would that
>>> reflect to, say, the DT presentation? Say, if we have a version A of the
>>> encoder, we could have DT data like this (just a rough example):
>>>
>>> soc-dsi {
>>> 	encoder {
>>> 		input: endpoint {
>>> 			remote-endpoint = <&soc-dsi-ep>;
>> Here I would replace &soc-dsi-ep by phandle to display controller/crtc/....
>>
>>> 			/* configuration for the DSI lanes */
>>> 			dsi-lanes = <0 1 2 3 4 5>;
>> Wow, quite advanced DSI.
> Wha? That just means there is one clock lane and two datalanes, nothing
> more =). We can select the polarity of a lane, so we describe both the
> positive and negative lines there. So it says clk- is connected to pin
> 0, clk+ connected to pin 1, etc.
OK in V4L binding world it means DSI with six lanes :)
>
>>> 		};
>>> 	};
>>> };
>>>
>>> So the encoder would be places inside the SoC's DSI node, similar to how
>>> an i2c device would be placed inside SoC's i2c node. DSI configuration
>>> would be inside the video endpoint data.
>>>
>>> Version B would be almost the same:
>>>
>>> &i2c0 {
>>> 	encoder {
>>> 		input: endpoint {
>>> 			remote-endpoint = <&soc-dsi-ep>;
>> &soc-dsi-ep => &disp-ctrl-ep
>>> 			/* configuration for the DSI lanes */
>>> 			dsi-lanes = <0 1 2 3 4 5>;
>>> 		};
>>> 	};
>>> };
>>>
>>> Now, how would the video-bus-less device be defined?
>>> It'd be inside the
>>> soc-dsi node, that's clear. Where would the DSI lane configuration be?
>>> Not inside 'endpoint' node, as that's for video and wouldn't exist in
>>> this case. Would we have the same lane configuration in two places, once
>>> for video and once for control?
>> I think it is control setting, so it should be put outside endpoint node.
>> Probably it could be placed in encoder node.
> Well, one point of the endpoints is also to allow "switching" of video
> devices.
>
> For example, I could have a board with a SoC's DSI output, connected to
> two DSI panels. There would be some kind of mux between, so that I can
> select which of the panels is actually connected to the SoC.
>
> Here the first panel could use 2 datalanes, the second one 4. Thus, the
> DSI master would have two endpoints, the other one using 2 and the other
> 4 datalanes.
>
> If we decide that kind of support is not needed, well, is there even
> need for the V4L2 endpoints in the DT data at all?
Hmm, both panels connected to one endpoint of dispc ?
The problem I see is which driver should handle panel switching,
but this is question about hardware design as well. If this is realized
by dispc I have told already the solution. If this is realized by other
device I do not see a problem to create corresponding CDF entity,
or maybe it can be handled by "Pipeline Controller" ???
>
>>> I agree that having DSI/DBI control and video separated would be
>>> elegant. But I'd like to hear what is the technical benefit of that? At
>>> least to me it's clearly more complex to separate them than to keep them
>>> together (to the extent that I don't yet see how it is even possible),
>>> so there must be a good reason for the separation. I don't understand
>>> that reason. What is it?
>> Roughly speaking it is a question where is the more convenient place to
>> put bunch
>> of opses, technically both solutions can be somehow implemented.
> Well, it's also about dividing a single physical bus into two separate
> interfaces to it. It sounds to me that it would be much more complex
> with locking. With a single API, we can just say "the caller handles
> locking". With two separate interfaces, there must be locking at the
> lower level.
We say then: callee handles locking :)
>
>> Pros of mipi bus:
>> - no fake entity in CDF, with fake opses, I have to use similar entities
>> in MIPI-CSI
>> camera pipelines and it complicates life without any benefit(at least
>> from user side),
> You mean the DSI-master? I don't see how it's "fake", it's a video
> processing unit that has to be configured. Even if we forget the control
> side, and just think about plain video stream with DSI video mode,
> there's are things to configure with it.
>
> What kind of issues you have in the CSI side, then?
Not real issues, just needless calls to configure CSI entity pads,
with the same format and picture sizes as in camera.

>
>> - CDF models only video buses, control bus is a domain of Linux buses,
> Yes, but in this case the buses are the same. It makes me a bit nervous
> to have two separate ways (video and control) to use the same bus, in a
> case like video where timing is critical.
>
> So yes, we can consider video and control buses as "virtual" buses, and
> the actual transport is the DSI bus. Maybe it can be done. It just makes
> me a bit nervous =).
>
>> - less platform_bus abusing,
> Well, platform.txt says
>
> "This pseudo-bus
> is used to connect devices on busses with minimal infrastructure,
> like those used to integrate peripherals on many system-on-chip
> processors, or some "legacy" PC interconnects; as opposed to large
> formally specified ones like PCI or USB."
>
> I don't think DSI and DBI as platform bus is that far from the
> description. They are "simple", no probing point-to-point (in practice)
> buses. There's not much "bus" to speak of, just a point-to-point link.
Next section:

Platform devices
~~~~~~~~~~~~~~~~
Platform devices are devices that typically appear as autonomous
entities in the system. This includes legacy port-based devices and
host bridges to peripheral buses, and most controllers integrated
into system-on-chip platforms.  What they usually have in common
is direct addressing from a CPU bus.  Rarely, a platform_device will
be connected through a segment of some other kind of bus; but its
registers will still be directly addressable.


>> - better device tree topology (at least for common cases),
> Even if we use platform devices for DSI peripherals, we can have them
> described under the DSI master node.
Sorry, I meant rather Linux device tree topology, not DT.
>
>> - quite simple in case of typical devices.
> Still more complex than single API for both video and control =).
I agree.

Andrzej

>  Tomi
>
>


^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
@ 2013-10-11 14:16                 ` Andrzej Hajda
  0 siblings, 0 replies; 83+ messages in thread
From: Andrzej Hajda @ 2013-10-11 14:16 UTC (permalink / raw)
  To: Tomi Valkeinen, Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

On 10/11/2013 02:30 PM, Tomi Valkeinen wrote:
> On 11/10/13 14:19, Andrzej Hajda wrote:
>> On 10/11/2013 08:37 AM, Tomi Valkeinen wrote:
>>> The minimum bta-timeout should be deducable from the DSI bus speed,
>>> shouldn't it? Thus there's no need to define it anywhere.
>> Hmm, specification says "This specified period shall be longer then
>> the maximum possible turnaround delay for the unit to which the
>> turnaround request was sent".
> Ah, you're right. We can't know how long the peripheral will take
> responding. I was thinking of something that only depends on the
> bus-speed and the timings for that.
>
>> If I undrestand correctly you think about CDF topology like below:
>>
>> DispContr(SoC) ---> DSI-master(SoC) ---> encoder(DSI or I2C)
>>
>> But I think with mipi-dsi-bus topology could look like:
>>
>> DispContr(SoC) ---> encoder(DSI or I2C)
>>
>> DSI-master will not have its own entity, in the graph it could be
>> represented
>> by the link(--->), as it really does not process the video, only
>> transports it.
> At least in OMAP, the SoC's DSI-master receives parallel RGB data from
> DISPC, and encodes it to DSI. Isn't that processing? It's basically a
> DPI-to-DSI encoder. And it's not a simple pass-through, the DSI video
> timings could be considerably different than the DPI timings.
Picture size, content and format is the same on input and on output of DSI.
The same bits which enters DSI appears on the output. Internally bits
order can
be different but practically you are configuring DSI master and slave
with the same format.

If you create DSI entity you will have to always set the same format and
size on DSI input, DSI output and encoder input.
If you skip creating DSI entity you loose nothing, and you do not need
to take care of it.

>
>> In case of version A I think everything is clear.
>> In case of version B it does not seems so nice at the first sight, but
>> still seems quite straightforward to me - special plink in encoder's
>> node pointing
>> to DSI-master, driver will find the device in runtime and use ops as needed
>> (additional ops/helpers required).
>> This is also the way to support devices which can be controlled by DSI
>> and I2C
>> in the same time. Anyway I suspect such scenario will be quite rare.
> Okay, so if I gather it right, you say there would be something like
> 'dsi_adapter' (like i2c_adapter), which represents the dsi-master. And a
> driver could get pointer to this, regardless of whether it the linux
> device is a DSI device.
>
> At least one issue with this approach is the endpoint problem (see below).
>
>>> And, if we want to separate the video and control, I see no reason to
>>> explicitly require the video side to be present. I.e. we could as well
>>> have a DSI peripheral that has only the control bus used. How would that
>>> reflect to, say, the DT presentation? Say, if we have a version A of the
>>> encoder, we could have DT data like this (just a rough example):
>>>
>>> soc-dsi {
>>> 	encoder {
>>> 		input: endpoint {
>>> 			remote-endpoint = <&soc-dsi-ep>;
>> Here I would replace &soc-dsi-ep by phandle to display controller/crtc/....
>>
>>> 			/* configuration for the DSI lanes */
>>> 			dsi-lanes = <0 1 2 3 4 5>;
>> Wow, quite advanced DSI.
> Wha? That just means there is one clock lane and two datalanes, nothing
> more =). We can select the polarity of a lane, so we describe both the
> positive and negative lines there. So it says clk- is connected to pin
> 0, clk+ connected to pin 1, etc.
OK in V4L binding world it means DSI with six lanes :)
>
>>> 		};
>>> 	};
>>> };
>>>
>>> So the encoder would be places inside the SoC's DSI node, similar to how
>>> an i2c device would be placed inside SoC's i2c node. DSI configuration
>>> would be inside the video endpoint data.
>>>
>>> Version B would be almost the same:
>>>
>>> &i2c0 {
>>> 	encoder {
>>> 		input: endpoint {
>>> 			remote-endpoint = <&soc-dsi-ep>;
>> &soc-dsi-ep => &disp-ctrl-ep
>>> 			/* configuration for the DSI lanes */
>>> 			dsi-lanes = <0 1 2 3 4 5>;
>>> 		};
>>> 	};
>>> };
>>>
>>> Now, how would the video-bus-less device be defined?
>>> It'd be inside the
>>> soc-dsi node, that's clear. Where would the DSI lane configuration be?
>>> Not inside 'endpoint' node, as that's for video and wouldn't exist in
>>> this case. Would we have the same lane configuration in two places, once
>>> for video and once for control?
>> I think it is control setting, so it should be put outside endpoint node.
>> Probably it could be placed in encoder node.
> Well, one point of the endpoints is also to allow "switching" of video
> devices.
>
> For example, I could have a board with a SoC's DSI output, connected to
> two DSI panels. There would be some kind of mux between, so that I can
> select which of the panels is actually connected to the SoC.
>
> Here the first panel could use 2 datalanes, the second one 4. Thus, the
> DSI master would have two endpoints, the other one using 2 and the other
> 4 datalanes.
>
> If we decide that kind of support is not needed, well, is there even
> need for the V4L2 endpoints in the DT data at all?
Hmm, both panels connected to one endpoint of dispc ?
The problem I see is which driver should handle panel switching,
but this is question about hardware design as well. If this is realized
by dispc I have told already the solution. If this is realized by other
device I do not see a problem to create corresponding CDF entity,
or maybe it can be handled by "Pipeline Controller" ???
>
>>> I agree that having DSI/DBI control and video separated would be
>>> elegant. But I'd like to hear what is the technical benefit of that? At
>>> least to me it's clearly more complex to separate them than to keep them
>>> together (to the extent that I don't yet see how it is even possible),
>>> so there must be a good reason for the separation. I don't understand
>>> that reason. What is it?
>> Roughly speaking it is a question where is the more convenient place to
>> put bunch
>> of opses, technically both solutions can be somehow implemented.
> Well, it's also about dividing a single physical bus into two separate
> interfaces to it. It sounds to me that it would be much more complex
> with locking. With a single API, we can just say "the caller handles
> locking". With two separate interfaces, there must be locking at the
> lower level.
We say then: callee handles locking :)
>
>> Pros of mipi bus:
>> - no fake entity in CDF, with fake opses, I have to use similar entities
>> in MIPI-CSI
>> camera pipelines and it complicates life without any benefit(at least
>> from user side),
> You mean the DSI-master? I don't see how it's "fake", it's a video
> processing unit that has to be configured. Even if we forget the control
> side, and just think about plain video stream with DSI video mode,
> there's are things to configure with it.
>
> What kind of issues you have in the CSI side, then?
Not real issues, just needless calls to configure CSI entity pads,
with the same format and picture sizes as in camera.

>
>> - CDF models only video buses, control bus is a domain of Linux buses,
> Yes, but in this case the buses are the same. It makes me a bit nervous
> to have two separate ways (video and control) to use the same bus, in a
> case like video where timing is critical.
>
> So yes, we can consider video and control buses as "virtual" buses, and
> the actual transport is the DSI bus. Maybe it can be done. It just makes
> me a bit nervous =).
>
>> - less platform_bus abusing,
> Well, platform.txt says
>
> "This pseudo-bus
> is used to connect devices on busses with minimal infrastructure,
> like those used to integrate peripherals on many system-on-chip
> processors, or some "legacy" PC interconnects; as opposed to large
> formally specified ones like PCI or USB."
>
> I don't think DSI and DBI as platform bus is that far from the
> description. They are "simple", no probing point-to-point (in practice)
> buses. There's not much "bus" to speak of, just a point-to-point link.
Next section:

Platform devices
~~~~~~~~~~~~~~~~
Platform devices are devices that typically appear as autonomous
entities in the system. This includes legacy port-based devices and
host bridges to peripheral buses, and most controllers integrated
into system-on-chip platforms.  What they usually have in common
is direct addressing from a CPU bus.  Rarely, a platform_device will
be connected through a segment of some other kind of bus; but its
registers will still be directly addressable.


>> - better device tree topology (at least for common cases),
> Even if we use platform devices for DSI peripherals, we can have them
> described under the DSI master node.
Sorry, I meant rather Linux device tree topology, not DT.
>
>> - quite simple in case of typical devices.
> Still more complex than single API for both video and control =).
I agree.

Andrzej

>  Tomi
>
>


^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
  2013-10-11 14:16                 ` Andrzej Hajda
  (?)
@ 2013-10-11 14:45                   ` Tomi Valkeinen
  -1 siblings, 0 replies; 83+ messages in thread
From: Tomi Valkeinen @ 2013-10-11 14:45 UTC (permalink / raw)
  To: Andrzej Hajda, Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

[-- Attachment #1: Type: text/plain, Size: 6916 bytes --]

On 11/10/13 17:16, Andrzej Hajda wrote:

> Picture size, content and format is the same on input and on output of DSI.
> The same bits which enters DSI appears on the output. Internally bits
> order can
> be different but practically you are configuring DSI master and slave
> with the same format.
> 
> If you create DSI entity you will have to always set the same format and
> size on DSI input, DSI output and encoder input.
> If you skip creating DSI entity you loose nothing, and you do not need
> to take care of it.

Well, this is really a different question from the bus problem. But
nothing says the DSI master cannot change the format or even size. For
sure it can change the video timings. The DSI master could even take two
parallel inputs, and combine them into one DSI output. You don't can't
what all the possible pieces of hardware do =).

If you have a bigger IP block that internally contains the DISPC and the
DSI, then, yes, you can combine them into one display entity. I don't
think that's correct, though. And if the DISPC and DSI are independent
blocks, then especially I think there must be an entity for the DSI
block, which will enable the powers, clocks, etc, when needed.

>> Well, one point of the endpoints is also to allow "switching" of video
>> devices.
>>
>> For example, I could have a board with a SoC's DSI output, connected to
>> two DSI panels. There would be some kind of mux between, so that I can
>> select which of the panels is actually connected to the SoC.
>>
>> Here the first panel could use 2 datalanes, the second one 4. Thus, the
>> DSI master would have two endpoints, the other one using 2 and the other
>> 4 datalanes.
>>
>> If we decide that kind of support is not needed, well, is there even
>> need for the V4L2 endpoints in the DT data at all?
> Hmm, both panels connected to one endpoint of dispc ?
> The problem I see is which driver should handle panel switching,
> but this is question about hardware design as well. If this is realized
> by dispc I have told already the solution. If this is realized by other
> device I do not see a problem to create corresponding CDF entity,
> or maybe it can be handled by "Pipeline Controller" ???

Well the switching could be automatic, when the panel power is enabled,
the DSI mux is switched for that panel. It's not relevant.

We still have two different endpoint configurations for the same
DSI-master port. If that configuration is in the DSI-master's port node,
not inside an endpoint data, then that can't be supported.

>>>> I agree that having DSI/DBI control and video separated would be
>>>> elegant. But I'd like to hear what is the technical benefit of that? At
>>>> least to me it's clearly more complex to separate them than to keep them
>>>> together (to the extent that I don't yet see how it is even possible),
>>>> so there must be a good reason for the separation. I don't understand
>>>> that reason. What is it?
>>> Roughly speaking it is a question where is the more convenient place to
>>> put bunch
>>> of opses, technically both solutions can be somehow implemented.
>> Well, it's also about dividing a single physical bus into two separate
>> interfaces to it. It sounds to me that it would be much more complex
>> with locking. With a single API, we can just say "the caller handles
>> locking". With two separate interfaces, there must be locking at the
>> lower level.
> We say then: callee handles locking :)

Sure, but my point was that the caller handling the locking is much
simpler than the callee handling locking. And the latter causes
atomicity issues, as the other API could be invoked in between two calls
for the first API.

But note that I'm not saying we should not implement bus model just
because it's more complex. We should go for bus model if it's better. I
just want to bring up these complexities, which I feel are quite more
difficult than with the simpler model.

>>> Pros of mipi bus:
>>> - no fake entity in CDF, with fake opses, I have to use similar entities
>>> in MIPI-CSI
>>> camera pipelines and it complicates life without any benefit(at least
>>> from user side),
>> You mean the DSI-master? I don't see how it's "fake", it's a video
>> processing unit that has to be configured. Even if we forget the control
>> side, and just think about plain video stream with DSI video mode,
>> there's are things to configure with it.
>>
>> What kind of issues you have in the CSI side, then?
> Not real issues, just needless calls to configure CSI entity pads,
> with the same format and picture sizes as in camera.

Well, the output of a component A is surely the same as the input of
component B, if B receives the data from A. So that does sound useless.
I don't do that kind of calls in my model.

>>> - CDF models only video buses, control bus is a domain of Linux buses,
>> Yes, but in this case the buses are the same. It makes me a bit nervous
>> to have two separate ways (video and control) to use the same bus, in a
>> case like video where timing is critical.
>>
>> So yes, we can consider video and control buses as "virtual" buses, and
>> the actual transport is the DSI bus. Maybe it can be done. It just makes
>> me a bit nervous =).
>>
>>> - less platform_bus abusing,
>> Well, platform.txt says
>>
>> "This pseudo-bus
>> is used to connect devices on busses with minimal infrastructure,
>> like those used to integrate peripherals on many system-on-chip
>> processors, or some "legacy" PC interconnects; as opposed to large
>> formally specified ones like PCI or USB."
>>
>> I don't think DSI and DBI as platform bus is that far from the
>> description. They are "simple", no probing point-to-point (in practice)
>> buses. There's not much "bus" to speak of, just a point-to-point link.
> Next section:
> 
> Platform devices
> ~~~~~~~~~~~~~~~~
> Platform devices are devices that typically appear as autonomous
> entities in the system. This includes legacy port-based devices and
> host bridges to peripheral buses, and most controllers integrated
> into system-on-chip platforms.  What they usually have in common
> is direct addressing from a CPU bus.  Rarely, a platform_device will
> be connected through a segment of some other kind of bus; but its
> registers will still be directly addressable.

Yep, "typically" and "rarely" =). I agree, it's not clear. I think there
are things with DBI/DSI that clearly point to a platform device, but
also the other way.

>>> - better device tree topology (at least for common cases),
>> Even if we use platform devices for DSI peripherals, we can have them
>> described under the DSI master node.
> Sorry, I meant rather Linux device tree topology, not DT.

We can have the DSI peripheral platform devices as children of the
DSI-master device.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
@ 2013-10-11 14:45                   ` Tomi Valkeinen
  0 siblings, 0 replies; 83+ messages in thread
From: Tomi Valkeinen @ 2013-10-11 14:45 UTC (permalink / raw)
  To: Andrzej Hajda, Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

[-- Attachment #1: Type: text/plain, Size: 6916 bytes --]

On 11/10/13 17:16, Andrzej Hajda wrote:

> Picture size, content and format is the same on input and on output of DSI.
> The same bits which enters DSI appears on the output. Internally bits
> order can
> be different but practically you are configuring DSI master and slave
> with the same format.
> 
> If you create DSI entity you will have to always set the same format and
> size on DSI input, DSI output and encoder input.
> If you skip creating DSI entity you loose nothing, and you do not need
> to take care of it.

Well, this is really a different question from the bus problem. But
nothing says the DSI master cannot change the format or even size. For
sure it can change the video timings. The DSI master could even take two
parallel inputs, and combine them into one DSI output. You don't can't
what all the possible pieces of hardware do =).

If you have a bigger IP block that internally contains the DISPC and the
DSI, then, yes, you can combine them into one display entity. I don't
think that's correct, though. And if the DISPC and DSI are independent
blocks, then especially I think there must be an entity for the DSI
block, which will enable the powers, clocks, etc, when needed.

>> Well, one point of the endpoints is also to allow "switching" of video
>> devices.
>>
>> For example, I could have a board with a SoC's DSI output, connected to
>> two DSI panels. There would be some kind of mux between, so that I can
>> select which of the panels is actually connected to the SoC.
>>
>> Here the first panel could use 2 datalanes, the second one 4. Thus, the
>> DSI master would have two endpoints, the other one using 2 and the other
>> 4 datalanes.
>>
>> If we decide that kind of support is not needed, well, is there even
>> need for the V4L2 endpoints in the DT data at all?
> Hmm, both panels connected to one endpoint of dispc ?
> The problem I see is which driver should handle panel switching,
> but this is question about hardware design as well. If this is realized
> by dispc I have told already the solution. If this is realized by other
> device I do not see a problem to create corresponding CDF entity,
> or maybe it can be handled by "Pipeline Controller" ???

Well the switching could be automatic, when the panel power is enabled,
the DSI mux is switched for that panel. It's not relevant.

We still have two different endpoint configurations for the same
DSI-master port. If that configuration is in the DSI-master's port node,
not inside an endpoint data, then that can't be supported.

>>>> I agree that having DSI/DBI control and video separated would be
>>>> elegant. But I'd like to hear what is the technical benefit of that? At
>>>> least to me it's clearly more complex to separate them than to keep them
>>>> together (to the extent that I don't yet see how it is even possible),
>>>> so there must be a good reason for the separation. I don't understand
>>>> that reason. What is it?
>>> Roughly speaking it is a question where is the more convenient place to
>>> put bunch
>>> of opses, technically both solutions can be somehow implemented.
>> Well, it's also about dividing a single physical bus into two separate
>> interfaces to it. It sounds to me that it would be much more complex
>> with locking. With a single API, we can just say "the caller handles
>> locking". With two separate interfaces, there must be locking at the
>> lower level.
> We say then: callee handles locking :)

Sure, but my point was that the caller handling the locking is much
simpler than the callee handling locking. And the latter causes
atomicity issues, as the other API could be invoked in between two calls
for the first API.

But note that I'm not saying we should not implement bus model just
because it's more complex. We should go for bus model if it's better. I
just want to bring up these complexities, which I feel are quite more
difficult than with the simpler model.

>>> Pros of mipi bus:
>>> - no fake entity in CDF, with fake opses, I have to use similar entities
>>> in MIPI-CSI
>>> camera pipelines and it complicates life without any benefit(at least
>>> from user side),
>> You mean the DSI-master? I don't see how it's "fake", it's a video
>> processing unit that has to be configured. Even if we forget the control
>> side, and just think about plain video stream with DSI video mode,
>> there's are things to configure with it.
>>
>> What kind of issues you have in the CSI side, then?
> Not real issues, just needless calls to configure CSI entity pads,
> with the same format and picture sizes as in camera.

Well, the output of a component A is surely the same as the input of
component B, if B receives the data from A. So that does sound useless.
I don't do that kind of calls in my model.

>>> - CDF models only video buses, control bus is a domain of Linux buses,
>> Yes, but in this case the buses are the same. It makes me a bit nervous
>> to have two separate ways (video and control) to use the same bus, in a
>> case like video where timing is critical.
>>
>> So yes, we can consider video and control buses as "virtual" buses, and
>> the actual transport is the DSI bus. Maybe it can be done. It just makes
>> me a bit nervous =).
>>
>>> - less platform_bus abusing,
>> Well, platform.txt says
>>
>> "This pseudo-bus
>> is used to connect devices on busses with minimal infrastructure,
>> like those used to integrate peripherals on many system-on-chip
>> processors, or some "legacy" PC interconnects; as opposed to large
>> formally specified ones like PCI or USB."
>>
>> I don't think DSI and DBI as platform bus is that far from the
>> description. They are "simple", no probing point-to-point (in practice)
>> buses. There's not much "bus" to speak of, just a point-to-point link.
> Next section:
> 
> Platform devices
> ~~~~~~~~~~~~~~~~
> Platform devices are devices that typically appear as autonomous
> entities in the system. This includes legacy port-based devices and
> host bridges to peripheral buses, and most controllers integrated
> into system-on-chip platforms.  What they usually have in common
> is direct addressing from a CPU bus.  Rarely, a platform_device will
> be connected through a segment of some other kind of bus; but its
> registers will still be directly addressable.

Yep, "typically" and "rarely" =). I agree, it's not clear. I think there
are things with DBI/DSI that clearly point to a platform device, but
also the other way.

>>> - better device tree topology (at least for common cases),
>> Even if we use platform devices for DSI peripherals, we can have them
>> described under the DSI master node.
> Sorry, I meant rather Linux device tree topology, not DT.

We can have the DSI peripheral platform devices as children of the
DSI-master device.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
@ 2013-10-11 14:45                   ` Tomi Valkeinen
  0 siblings, 0 replies; 83+ messages in thread
From: Tomi Valkeinen @ 2013-10-11 14:45 UTC (permalink / raw)
  To: Andrzej Hajda, Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

[-- Attachment #1: Type: text/plain, Size: 6916 bytes --]

On 11/10/13 17:16, Andrzej Hajda wrote:

> Picture size, content and format is the same on input and on output of DSI.
> The same bits which enters DSI appears on the output. Internally bits
> order can
> be different but practically you are configuring DSI master and slave
> with the same format.
> 
> If you create DSI entity you will have to always set the same format and
> size on DSI input, DSI output and encoder input.
> If you skip creating DSI entity you loose nothing, and you do not need
> to take care of it.

Well, this is really a different question from the bus problem. But
nothing says the DSI master cannot change the format or even size. For
sure it can change the video timings. The DSI master could even take two
parallel inputs, and combine them into one DSI output. You don't can't
what all the possible pieces of hardware do =).

If you have a bigger IP block that internally contains the DISPC and the
DSI, then, yes, you can combine them into one display entity. I don't
think that's correct, though. And if the DISPC and DSI are independent
blocks, then especially I think there must be an entity for the DSI
block, which will enable the powers, clocks, etc, when needed.

>> Well, one point of the endpoints is also to allow "switching" of video
>> devices.
>>
>> For example, I could have a board with a SoC's DSI output, connected to
>> two DSI panels. There would be some kind of mux between, so that I can
>> select which of the panels is actually connected to the SoC.
>>
>> Here the first panel could use 2 datalanes, the second one 4. Thus, the
>> DSI master would have two endpoints, the other one using 2 and the other
>> 4 datalanes.
>>
>> If we decide that kind of support is not needed, well, is there even
>> need for the V4L2 endpoints in the DT data at all?
> Hmm, both panels connected to one endpoint of dispc ?
> The problem I see is which driver should handle panel switching,
> but this is question about hardware design as well. If this is realized
> by dispc I have told already the solution. If this is realized by other
> device I do not see a problem to create corresponding CDF entity,
> or maybe it can be handled by "Pipeline Controller" ???

Well the switching could be automatic, when the panel power is enabled,
the DSI mux is switched for that panel. It's not relevant.

We still have two different endpoint configurations for the same
DSI-master port. If that configuration is in the DSI-master's port node,
not inside an endpoint data, then that can't be supported.

>>>> I agree that having DSI/DBI control and video separated would be
>>>> elegant. But I'd like to hear what is the technical benefit of that? At
>>>> least to me it's clearly more complex to separate them than to keep them
>>>> together (to the extent that I don't yet see how it is even possible),
>>>> so there must be a good reason for the separation. I don't understand
>>>> that reason. What is it?
>>> Roughly speaking it is a question where is the more convenient place to
>>> put bunch
>>> of opses, technically both solutions can be somehow implemented.
>> Well, it's also about dividing a single physical bus into two separate
>> interfaces to it. It sounds to me that it would be much more complex
>> with locking. With a single API, we can just say "the caller handles
>> locking". With two separate interfaces, there must be locking at the
>> lower level.
> We say then: callee handles locking :)

Sure, but my point was that the caller handling the locking is much
simpler than the callee handling locking. And the latter causes
atomicity issues, as the other API could be invoked in between two calls
for the first API.

But note that I'm not saying we should not implement bus model just
because it's more complex. We should go for bus model if it's better. I
just want to bring up these complexities, which I feel are quite more
difficult than with the simpler model.

>>> Pros of mipi bus:
>>> - no fake entity in CDF, with fake opses, I have to use similar entities
>>> in MIPI-CSI
>>> camera pipelines and it complicates life without any benefit(at least
>>> from user side),
>> You mean the DSI-master? I don't see how it's "fake", it's a video
>> processing unit that has to be configured. Even if we forget the control
>> side, and just think about plain video stream with DSI video mode,
>> there's are things to configure with it.
>>
>> What kind of issues you have in the CSI side, then?
> Not real issues, just needless calls to configure CSI entity pads,
> with the same format and picture sizes as in camera.

Well, the output of a component A is surely the same as the input of
component B, if B receives the data from A. So that does sound useless.
I don't do that kind of calls in my model.

>>> - CDF models only video buses, control bus is a domain of Linux buses,
>> Yes, but in this case the buses are the same. It makes me a bit nervous
>> to have two separate ways (video and control) to use the same bus, in a
>> case like video where timing is critical.
>>
>> So yes, we can consider video and control buses as "virtual" buses, and
>> the actual transport is the DSI bus. Maybe it can be done. It just makes
>> me a bit nervous =).
>>
>>> - less platform_bus abusing,
>> Well, platform.txt says
>>
>> "This pseudo-bus
>> is used to connect devices on busses with minimal infrastructure,
>> like those used to integrate peripherals on many system-on-chip
>> processors, or some "legacy" PC interconnects; as opposed to large
>> formally specified ones like PCI or USB."
>>
>> I don't think DSI and DBI as platform bus is that far from the
>> description. They are "simple", no probing point-to-point (in practice)
>> buses. There's not much "bus" to speak of, just a point-to-point link.
> Next section:
> 
> Platform devices
> ~~~~~~~~~~~~~~~~
> Platform devices are devices that typically appear as autonomous
> entities in the system. This includes legacy port-based devices and
> host bridges to peripheral buses, and most controllers integrated
> into system-on-chip platforms.  What they usually have in common
> is direct addressing from a CPU bus.  Rarely, a platform_device will
> be connected through a segment of some other kind of bus; but its
> registers will still be directly addressable.

Yep, "typically" and "rarely" =). I agree, it's not clear. I think there
are things with DBI/DSI that clearly point to a platform device, but
also the other way.

>>> - better device tree topology (at least for common cases),
>> Even if we use platform devices for DSI peripherals, we can have them
>> described under the DSI master node.
> Sorry, I meant rather Linux device tree topology, not DT.

We can have the DSI peripheral platform devices as children of the
DSI-master device.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
  2013-10-11 14:45                   ` Tomi Valkeinen
@ 2013-10-17  7:48                     ` Andrzej Hajda
  -1 siblings, 0 replies; 83+ messages in thread
From: Andrzej Hajda @ 2013-10-17  7:48 UTC (permalink / raw)
  To: Tomi Valkeinen, Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

Hi Tomi,

Sorry for delayed response.


On 10/11/2013 04:45 PM, Tomi Valkeinen wrote:
> On 11/10/13 17:16, Andrzej Hajda wrote:
>
>> Picture size, content and format is the same on input and on output of DSI.
>> The same bits which enters DSI appears on the output. Internally bits
>> order can
>> be different but practically you are configuring DSI master and slave
>> with the same format.
>>
>> If you create DSI entity you will have to always set the same format and
>> size on DSI input, DSI output and encoder input.
>> If you skip creating DSI entity you loose nothing, and you do not need
>> to take care of it.
> Well, this is really a different question from the bus problem. But
> nothing says the DSI master cannot change the format or even size. For
> sure it can change the video timings. The DSI master could even take two
> parallel inputs, and combine them into one DSI output. You don't can't
> what all the possible pieces of hardware do =)
> If you have a bigger IP block that internally contains the DISPC and the
> DSI, then, yes, you can combine them into one display entity. I don't
> think that's correct, though. And if the DISPC and DSI are independent
> blocks, then especially I think there must be an entity for the DSI
> block, which will enable the powers, clocks, etc, when needed.
The main function of DSI is to transport pixels from one IP to another IP
and this function IMO should not be modeled by display entity.
"Power, clocks, etc" will be performed via control bus according to
panel demands.
If 'DSI chip' has additional functions for video processing they can
be modeled by CDF entity if it makes sense.
>>> Well, one point of the endpoints is also to allow "switching" of video
>>> devices.
>>>
>>> For example, I could have a board with a SoC's DSI output, connected to
>>> two DSI panels. There would be some kind of mux between, so that I can
>>> select which of the panels is actually connected to the SoC.
>>>
>>> Here the first panel could use 2 datalanes, the second one 4. Thus, the
>>> DSI master would have two endpoints, the other one using 2 and the other
>>> 4 datalanes.
>>>
>>> If we decide that kind of support is not needed, well, is there even
>>> need for the V4L2 endpoints in the DT data at all?
>> Hmm, both panels connected to one endpoint of dispc ?
>> The problem I see is which driver should handle panel switching,
>> but this is question about hardware design as well. If this is realized
>> by dispc I have told already the solution. If this is realized by other
>> device I do not see a problem to create corresponding CDF entity,
>> or maybe it can be handled by "Pipeline Controller" ???
> Well the switching could be automatic, when the panel power is enabled,
> the DSI mux is switched for that panel. It's not relevant.
>
> We still have two different endpoint configurations for the same
> DSI-master port. If that configuration is in the DSI-master's port node,
> not inside an endpoint data, then that can't be supported.
I am not sure if I understand it correctly. But it seems quite simple:
when panel starts/resumes it request DSI (via control bus) to fulfill
its configuration settings.
Of course there are some settings which are not panel dependent and those
should reside in DSI node.
>>>>> I agree that having DSI/DBI control and video separated would be
>>>>> elegant. But I'd like to hear what is the technical benefit of that? At
>>>>> least to me it's clearly more complex to separate them than to keep them
>>>>> together (to the extent that I don't yet see how it is even possible),
>>>>> so there must be a good reason for the separation. I don't understand
>>>>> that reason. What is it?
>>>> Roughly speaking it is a question where is the more convenient place to
>>>> put bunch
>>>> of opses, technically both solutions can be somehow implemented.
>>> Well, it's also about dividing a single physical bus into two separate
>>> interfaces to it. It sounds to me that it would be much more complex
>>> with locking. With a single API, we can just say "the caller handles
>>> locking". With two separate interfaces, there must be locking at the
>>> lower level.
>> We say then: callee handles locking :)
> Sure, but my point was that the caller handling the locking is much
> simpler than the callee handling locking. And the latter causes
> atomicity issues, as the other API could be invoked in between two calls
> for the first API.
>
>     
Could you describe such scenario?
> But note that I'm not saying we should not implement bus model just
> because it's more complex. We should go for bus model if it's better. I
> just want to bring up these complexities, which I feel are quite more
> difficult than with the simpler model.
>
>>>> Pros of mipi bus:
>>>> - no fake entity in CDF, with fake opses, I have to use similar entities
>>>> in MIPI-CSI
>>>> camera pipelines and it complicates life without any benefit(at least
>>>> from user side),
>>> You mean the DSI-master? I don't see how it's "fake", it's a video
>>> processing unit that has to be configured. Even if we forget the control
>>> side, and just think about plain video stream with DSI video mode,
>>> there's are things to configure with it.
>>>
>>> What kind of issues you have in the CSI side, then?
>> Not real issues, just needless calls to configure CSI entity pads,
>> with the same format and picture sizes as in camera.
> Well, the output of a component A is surely the same as the input of
> component B, if B receives the data from A. So that does sound useless.
> I don't do that kind of calls in my model.
>
>>>> - CDF models only video buses, control bus is a domain of Linux buses,
>>> Yes, but in this case the buses are the same. It makes me a bit nervous
>>> to have two separate ways (video and control) to use the same bus, in a
>>> case like video where timing is critical.
>>>
>>> So yes, we can consider video and control buses as "virtual" buses, and
>>> the actual transport is the DSI bus. Maybe it can be done. It just makes
>>> me a bit nervous =).
>>>
>>>> - less platform_bus abusing,
>>> Well, platform.txt says
>>>
>>> "This pseudo-bus
>>> is used to connect devices on busses with minimal infrastructure,
>>> like those used to integrate peripherals on many system-on-chip
>>> processors, or some "legacy" PC interconnects; as opposed to large
>>> formally specified ones like PCI or USB."
>>>
>>> I don't think DSI and DBI as platform bus is that far from the
>>> description. They are "simple", no probing point-to-point (in practice)
>>> buses. There's not much "bus" to speak of, just a point-to-point link.
>> Next section:
>>
>> Platform devices
>> ~~~~~~~~~~~~~~~~
>> Platform devices are devices that typically appear as autonomous
>> entities in the system. This includes legacy port-based devices and
>> host bridges to peripheral buses, and most controllers integrated
>> into system-on-chip platforms.  What they usually have in common
>> is direct addressing from a CPU bus.  Rarely, a platform_device will
>> be connected through a segment of some other kind of bus; but its
>> registers will still be directly addressable.
> Yep, "typically" and "rarely" =). I agree, it's not clear. I think there
> are things with DBI/DSI that clearly point to a platform device, but
> also the other way.
Just to be sure, we are talking here about DSI-slaves, ie. for example
about panels,
where direct accessing from CPU bus usually is not possible.

Andrzej
>>>> - better device tree topology (at least for common cases),
>>> Even if we use platform devices for DSI peripherals, we can have them
>>> described under the DSI master node.
>> Sorry, I meant rather Linux device tree topology, not DT.
> We can have the DSI peripheral platform devices as children of the
> DSI-master device.
>
>  Tomi
>
>


^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
@ 2013-10-17  7:48                     ` Andrzej Hajda
  0 siblings, 0 replies; 83+ messages in thread
From: Andrzej Hajda @ 2013-10-17  7:48 UTC (permalink / raw)
  To: Tomi Valkeinen, Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

Hi Tomi,

Sorry for delayed response.


On 10/11/2013 04:45 PM, Tomi Valkeinen wrote:
> On 11/10/13 17:16, Andrzej Hajda wrote:
>
>> Picture size, content and format is the same on input and on output of DSI.
>> The same bits which enters DSI appears on the output. Internally bits
>> order can
>> be different but practically you are configuring DSI master and slave
>> with the same format.
>>
>> If you create DSI entity you will have to always set the same format and
>> size on DSI input, DSI output and encoder input.
>> If you skip creating DSI entity you loose nothing, and you do not need
>> to take care of it.
> Well, this is really a different question from the bus problem. But
> nothing says the DSI master cannot change the format or even size. For
> sure it can change the video timings. The DSI master could even take two
> parallel inputs, and combine them into one DSI output. You don't can't
> what all the possible pieces of hardware do =)
> If you have a bigger IP block that internally contains the DISPC and the
> DSI, then, yes, you can combine them into one display entity. I don't
> think that's correct, though. And if the DISPC and DSI are independent
> blocks, then especially I think there must be an entity for the DSI
> block, which will enable the powers, clocks, etc, when needed.
The main function of DSI is to transport pixels from one IP to another IP
and this function IMO should not be modeled by display entity.
"Power, clocks, etc" will be performed via control bus according to
panel demands.
If 'DSI chip' has additional functions for video processing they can
be modeled by CDF entity if it makes sense.
>>> Well, one point of the endpoints is also to allow "switching" of video
>>> devices.
>>>
>>> For example, I could have a board with a SoC's DSI output, connected to
>>> two DSI panels. There would be some kind of mux between, so that I can
>>> select which of the panels is actually connected to the SoC.
>>>
>>> Here the first panel could use 2 datalanes, the second one 4. Thus, the
>>> DSI master would have two endpoints, the other one using 2 and the other
>>> 4 datalanes.
>>>
>>> If we decide that kind of support is not needed, well, is there even
>>> need for the V4L2 endpoints in the DT data at all?
>> Hmm, both panels connected to one endpoint of dispc ?
>> The problem I see is which driver should handle panel switching,
>> but this is question about hardware design as well. If this is realized
>> by dispc I have told already the solution. If this is realized by other
>> device I do not see a problem to create corresponding CDF entity,
>> or maybe it can be handled by "Pipeline Controller" ???
> Well the switching could be automatic, when the panel power is enabled,
> the DSI mux is switched for that panel. It's not relevant.
>
> We still have two different endpoint configurations for the same
> DSI-master port. If that configuration is in the DSI-master's port node,
> not inside an endpoint data, then that can't be supported.
I am not sure if I understand it correctly. But it seems quite simple:
when panel starts/resumes it request DSI (via control bus) to fulfill
its configuration settings.
Of course there are some settings which are not panel dependent and those
should reside in DSI node.
>>>>> I agree that having DSI/DBI control and video separated would be
>>>>> elegant. But I'd like to hear what is the technical benefit of that? At
>>>>> least to me it's clearly more complex to separate them than to keep them
>>>>> together (to the extent that I don't yet see how it is even possible),
>>>>> so there must be a good reason for the separation. I don't understand
>>>>> that reason. What is it?
>>>> Roughly speaking it is a question where is the more convenient place to
>>>> put bunch
>>>> of opses, technically both solutions can be somehow implemented.
>>> Well, it's also about dividing a single physical bus into two separate
>>> interfaces to it. It sounds to me that it would be much more complex
>>> with locking. With a single API, we can just say "the caller handles
>>> locking". With two separate interfaces, there must be locking at the
>>> lower level.
>> We say then: callee handles locking :)
> Sure, but my point was that the caller handling the locking is much
> simpler than the callee handling locking. And the latter causes
> atomicity issues, as the other API could be invoked in between two calls
> for the first API.
>
>     
Could you describe such scenario?
> But note that I'm not saying we should not implement bus model just
> because it's more complex. We should go for bus model if it's better. I
> just want to bring up these complexities, which I feel are quite more
> difficult than with the simpler model.
>
>>>> Pros of mipi bus:
>>>> - no fake entity in CDF, with fake opses, I have to use similar entities
>>>> in MIPI-CSI
>>>> camera pipelines and it complicates life without any benefit(at least
>>>> from user side),
>>> You mean the DSI-master? I don't see how it's "fake", it's a video
>>> processing unit that has to be configured. Even if we forget the control
>>> side, and just think about plain video stream with DSI video mode,
>>> there's are things to configure with it.
>>>
>>> What kind of issues you have in the CSI side, then?
>> Not real issues, just needless calls to configure CSI entity pads,
>> with the same format and picture sizes as in camera.
> Well, the output of a component A is surely the same as the input of
> component B, if B receives the data from A. So that does sound useless.
> I don't do that kind of calls in my model.
>
>>>> - CDF models only video buses, control bus is a domain of Linux buses,
>>> Yes, but in this case the buses are the same. It makes me a bit nervous
>>> to have two separate ways (video and control) to use the same bus, in a
>>> case like video where timing is critical.
>>>
>>> So yes, we can consider video and control buses as "virtual" buses, and
>>> the actual transport is the DSI bus. Maybe it can be done. It just makes
>>> me a bit nervous =).
>>>
>>>> - less platform_bus abusing,
>>> Well, platform.txt says
>>>
>>> "This pseudo-bus
>>> is used to connect devices on busses with minimal infrastructure,
>>> like those used to integrate peripherals on many system-on-chip
>>> processors, or some "legacy" PC interconnects; as opposed to large
>>> formally specified ones like PCI or USB."
>>>
>>> I don't think DSI and DBI as platform bus is that far from the
>>> description. They are "simple", no probing point-to-point (in practice)
>>> buses. There's not much "bus" to speak of, just a point-to-point link.
>> Next section:
>>
>> Platform devices
>> ~~~~~~~~~~~~~~~~
>> Platform devices are devices that typically appear as autonomous
>> entities in the system. This includes legacy port-based devices and
>> host bridges to peripheral buses, and most controllers integrated
>> into system-on-chip platforms.  What they usually have in common
>> is direct addressing from a CPU bus.  Rarely, a platform_device will
>> be connected through a segment of some other kind of bus; but its
>> registers will still be directly addressable.
> Yep, "typically" and "rarely" =). I agree, it's not clear. I think there
> are things with DBI/DSI that clearly point to a platform device, but
> also the other way.
Just to be sure, we are talking here about DSI-slaves, ie. for example
about panels,
where direct accessing from CPU bus usually is not possible.

Andrzej
>>>> - better device tree topology (at least for common cases),
>>> Even if we use platform devices for DSI peripherals, we can have them
>>> described under the DSI master node.
>> Sorry, I meant rather Linux device tree topology, not DT.
> We can have the DSI peripheral platform devices as children of the
> DSI-master device.
>
>  Tomi
>
>


^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
  2013-10-17  7:48                     ` Andrzej Hajda
  (?)
@ 2013-10-17  8:18                       ` Tomi Valkeinen
  -1 siblings, 0 replies; 83+ messages in thread
From: Tomi Valkeinen @ 2013-10-17  8:18 UTC (permalink / raw)
  To: Andrzej Hajda, Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

[-- Attachment #1: Type: text/plain, Size: 4411 bytes --]

On 17/10/13 10:48, Andrzej Hajda wrote:

> The main function of DSI is to transport pixels from one IP to another IP
> and this function IMO should not be modeled by display entity.
> "Power, clocks, etc" will be performed via control bus according to
> panel demands.
> If 'DSI chip' has additional functions for video processing they can
> be modeled by CDF entity if it makes sense.

Now I don't follow. What do you mean with "display entity" and with "CDF
entity"? Are they the same?

Let me try to clarify my point:

On OMAP SoC we have a DSI encoder, which takes input from the display
controller in parallel RGB format, and outputs DSI.

Then there are external encoders that take MIPI DPI as input, and output
DSI.

The only difference with the above two components is that the first one
is embedded into the SoC. I see no reason to represent them in different
ways (i.e. as you suggested, not representing the SoC's DSI at all).

Also, if you use DSI burst mode, you will have to have different video
timings in the DSI encoder's input and output. And depending on the
buffering of the DSI encoder, you could have different timings in any case.

Furthermore, both components could have extra processing. I know the
external encoders sometimes do have features like scaling.

>> We still have two different endpoint configurations for the same
>> DSI-master port. If that configuration is in the DSI-master's port node,
>> not inside an endpoint data, then that can't be supported.
> I am not sure if I understand it correctly. But it seems quite simple:
> when panel starts/resumes it request DSI (via control bus) to fulfill
> its configuration settings.
> Of course there are some settings which are not panel dependent and those
> should reside in DSI node.

Exactly. And when the two panels require different non-panel-dependent
settings, how do you represent them in the DT data?

>>> We say then: callee handles locking :)
>> Sure, but my point was that the caller handling the locking is much
>> simpler than the callee handling locking. And the latter causes
>> atomicity issues, as the other API could be invoked in between two calls
>> for the first API.
>>
>>     
> Could you describe such scenario?

If we have two independent APIs, ctrl and video, that affect the same
underlying hardware, the DSI bus, we could have a scenario like this:

thread 1:

ctrl->op_foo();
ctrl->op_bar();

thread 2:

video->op_baz();

Even if all those ops do locking properly internally, the fact that
op_baz() can be called in between op_foo() and op_bar() may cause problems.

To avoid that issue with two APIs we'd need something like:

thread 1:

ctrl->lock();
ctrl->op_foo();
ctrl->op_bar();
ctrl->unlock();

thread 2:

video->lock();
video->op_baz();
video->unlock();

>>> Platform devices
>>> ~~~~~~~~~~~~~~~~
>>> Platform devices are devices that typically appear as autonomous
>>> entities in the system. This includes legacy port-based devices and
>>> host bridges to peripheral buses, and most controllers integrated
>>> into system-on-chip platforms.  What they usually have in common
>>> is direct addressing from a CPU bus.  Rarely, a platform_device will
>>> be connected through a segment of some other kind of bus; but its
>>> registers will still be directly addressable.
>> Yep, "typically" and "rarely" =). I agree, it's not clear. I think there
>> are things with DBI/DSI that clearly point to a platform device, but
>> also the other way.
> Just to be sure, we are talking here about DSI-slaves, ie. for example
> about panels,
> where direct accessing from CPU bus usually is not possible.

Yes. My point is that with DBI/DSI there's not much bus there (if a
normal bus would be PCI/USB/i2c etc), it's just a point to point link
without probing or a clearly specified setup sequence.

If DSI/DBI was used only for control, a linux bus would probably make
sense. But DSI/DBI is mainly a video transport channel, with the
control-part being "secondary".

And when considering that the video and control data are sent over the
same channel (i.e. there's no separate, independent ctrl channel), and
the strict timing restrictions with video, my gut feeling is just that
all the extra complexity brought with separating the control to a
separate bus is not worth it.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
@ 2013-10-17  8:18                       ` Tomi Valkeinen
  0 siblings, 0 replies; 83+ messages in thread
From: Tomi Valkeinen @ 2013-10-17  8:18 UTC (permalink / raw)
  To: Andrzej Hajda, Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

[-- Attachment #1: Type: text/plain, Size: 4411 bytes --]

On 17/10/13 10:48, Andrzej Hajda wrote:

> The main function of DSI is to transport pixels from one IP to another IP
> and this function IMO should not be modeled by display entity.
> "Power, clocks, etc" will be performed via control bus according to
> panel demands.
> If 'DSI chip' has additional functions for video processing they can
> be modeled by CDF entity if it makes sense.

Now I don't follow. What do you mean with "display entity" and with "CDF
entity"? Are they the same?

Let me try to clarify my point:

On OMAP SoC we have a DSI encoder, which takes input from the display
controller in parallel RGB format, and outputs DSI.

Then there are external encoders that take MIPI DPI as input, and output
DSI.

The only difference with the above two components is that the first one
is embedded into the SoC. I see no reason to represent them in different
ways (i.e. as you suggested, not representing the SoC's DSI at all).

Also, if you use DSI burst mode, you will have to have different video
timings in the DSI encoder's input and output. And depending on the
buffering of the DSI encoder, you could have different timings in any case.

Furthermore, both components could have extra processing. I know the
external encoders sometimes do have features like scaling.

>> We still have two different endpoint configurations for the same
>> DSI-master port. If that configuration is in the DSI-master's port node,
>> not inside an endpoint data, then that can't be supported.
> I am not sure if I understand it correctly. But it seems quite simple:
> when panel starts/resumes it request DSI (via control bus) to fulfill
> its configuration settings.
> Of course there are some settings which are not panel dependent and those
> should reside in DSI node.

Exactly. And when the two panels require different non-panel-dependent
settings, how do you represent them in the DT data?

>>> We say then: callee handles locking :)
>> Sure, but my point was that the caller handling the locking is much
>> simpler than the callee handling locking. And the latter causes
>> atomicity issues, as the other API could be invoked in between two calls
>> for the first API.
>>
>>     
> Could you describe such scenario?

If we have two independent APIs, ctrl and video, that affect the same
underlying hardware, the DSI bus, we could have a scenario like this:

thread 1:

ctrl->op_foo();
ctrl->op_bar();

thread 2:

video->op_baz();

Even if all those ops do locking properly internally, the fact that
op_baz() can be called in between op_foo() and op_bar() may cause problems.

To avoid that issue with two APIs we'd need something like:

thread 1:

ctrl->lock();
ctrl->op_foo();
ctrl->op_bar();
ctrl->unlock();

thread 2:

video->lock();
video->op_baz();
video->unlock();

>>> Platform devices
>>> ~~~~~~~~~~~~~~~~
>>> Platform devices are devices that typically appear as autonomous
>>> entities in the system. This includes legacy port-based devices and
>>> host bridges to peripheral buses, and most controllers integrated
>>> into system-on-chip platforms.  What they usually have in common
>>> is direct addressing from a CPU bus.  Rarely, a platform_device will
>>> be connected through a segment of some other kind of bus; but its
>>> registers will still be directly addressable.
>> Yep, "typically" and "rarely" =). I agree, it's not clear. I think there
>> are things with DBI/DSI that clearly point to a platform device, but
>> also the other way.
> Just to be sure, we are talking here about DSI-slaves, ie. for example
> about panels,
> where direct accessing from CPU bus usually is not possible.

Yes. My point is that with DBI/DSI there's not much bus there (if a
normal bus would be PCI/USB/i2c etc), it's just a point to point link
without probing or a clearly specified setup sequence.

If DSI/DBI was used only for control, a linux bus would probably make
sense. But DSI/DBI is mainly a video transport channel, with the
control-part being "secondary".

And when considering that the video and control data are sent over the
same channel (i.e. there's no separate, independent ctrl channel), and
the strict timing restrictions with video, my gut feeling is just that
all the extra complexity brought with separating the control to a
separate bus is not worth it.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
@ 2013-10-17  8:18                       ` Tomi Valkeinen
  0 siblings, 0 replies; 83+ messages in thread
From: Tomi Valkeinen @ 2013-10-17  8:18 UTC (permalink / raw)
  To: Andrzej Hajda, Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

[-- Attachment #1: Type: text/plain, Size: 4411 bytes --]

On 17/10/13 10:48, Andrzej Hajda wrote:

> The main function of DSI is to transport pixels from one IP to another IP
> and this function IMO should not be modeled by display entity.
> "Power, clocks, etc" will be performed via control bus according to
> panel demands.
> If 'DSI chip' has additional functions for video processing they can
> be modeled by CDF entity if it makes sense.

Now I don't follow. What do you mean with "display entity" and with "CDF
entity"? Are they the same?

Let me try to clarify my point:

On OMAP SoC we have a DSI encoder, which takes input from the display
controller in parallel RGB format, and outputs DSI.

Then there are external encoders that take MIPI DPI as input, and output
DSI.

The only difference with the above two components is that the first one
is embedded into the SoC. I see no reason to represent them in different
ways (i.e. as you suggested, not representing the SoC's DSI at all).

Also, if you use DSI burst mode, you will have to have different video
timings in the DSI encoder's input and output. And depending on the
buffering of the DSI encoder, you could have different timings in any case.

Furthermore, both components could have extra processing. I know the
external encoders sometimes do have features like scaling.

>> We still have two different endpoint configurations for the same
>> DSI-master port. If that configuration is in the DSI-master's port node,
>> not inside an endpoint data, then that can't be supported.
> I am not sure if I understand it correctly. But it seems quite simple:
> when panel starts/resumes it request DSI (via control bus) to fulfill
> its configuration settings.
> Of course there are some settings which are not panel dependent and those
> should reside in DSI node.

Exactly. And when the two panels require different non-panel-dependent
settings, how do you represent them in the DT data?

>>> We say then: callee handles locking :)
>> Sure, but my point was that the caller handling the locking is much
>> simpler than the callee handling locking. And the latter causes
>> atomicity issues, as the other API could be invoked in between two calls
>> for the first API.
>>
>>     
> Could you describe such scenario?

If we have two independent APIs, ctrl and video, that affect the same
underlying hardware, the DSI bus, we could have a scenario like this:

thread 1:

ctrl->op_foo();
ctrl->op_bar();

thread 2:

video->op_baz();

Even if all those ops do locking properly internally, the fact that
op_baz() can be called in between op_foo() and op_bar() may cause problems.

To avoid that issue with two APIs we'd need something like:

thread 1:

ctrl->lock();
ctrl->op_foo();
ctrl->op_bar();
ctrl->unlock();

thread 2:

video->lock();
video->op_baz();
video->unlock();

>>> Platform devices
>>> ~~~~~~~~~~~~~~~~
>>> Platform devices are devices that typically appear as autonomous
>>> entities in the system. This includes legacy port-based devices and
>>> host bridges to peripheral buses, and most controllers integrated
>>> into system-on-chip platforms.  What they usually have in common
>>> is direct addressing from a CPU bus.  Rarely, a platform_device will
>>> be connected through a segment of some other kind of bus; but its
>>> registers will still be directly addressable.
>> Yep, "typically" and "rarely" =). I agree, it's not clear. I think there
>> are things with DBI/DSI that clearly point to a platform device, but
>> also the other way.
> Just to be sure, we are talking here about DSI-slaves, ie. for example
> about panels,
> where direct accessing from CPU bus usually is not possible.

Yes. My point is that with DBI/DSI there's not much bus there (if a
normal bus would be PCI/USB/i2c etc), it's just a point to point link
without probing or a clearly specified setup sequence.

If DSI/DBI was used only for control, a linux bus would probably make
sense. But DSI/DBI is mainly a video transport channel, with the
control-part being "secondary".

And when considering that the video and control data are sent over the
same channel (i.e. there's no separate, independent ctrl channel), and
the strict timing restrictions with video, my gut feeling is just that
all the extra complexity brought with separating the control to a
separate bus is not worth it.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
  2013-10-17  8:18                       ` Tomi Valkeinen
@ 2013-10-17 12:26                         ` Andrzej Hajda
  -1 siblings, 0 replies; 83+ messages in thread
From: Andrzej Hajda @ 2013-10-17 12:26 UTC (permalink / raw)
  To: Tomi Valkeinen, Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

On 10/17/2013 10:18 AM, Tomi Valkeinen wrote:
> On 17/10/13 10:48, Andrzej Hajda wrote:
>
>> The main function of DSI is to transport pixels from one IP to another IP
>> and this function IMO should not be modeled by display entity.
>> "Power, clocks, etc" will be performed via control bus according to
>> panel demands.
>> If 'DSI chip' has additional functions for video processing they can
>> be modeled by CDF entity if it makes sense.
> Now I don't follow. What do you mean with "display entity" and with "CDF
> entity"? Are they the same?
Yes, they are the same, sorry for confusion.
>
> Let me try to clarify my point:
>
> On OMAP SoC we have a DSI encoder, which takes input from the display
> controller in parallel RGB format, and outputs DSI.
>
> Then there are external encoders that take MIPI DPI as input, and output
> DSI.
>
> The only difference with the above two components is that the first one
> is embedded into the SoC. I see no reason to represent them in different
> ways (i.e. as you suggested, not representing the SoC's DSI at all).
>
> Also, if you use DSI burst mode, you will have to have different video
> timings in the DSI encoder's input and output. And depending on the
> buffering of the DSI encoder, you could have different timings in any case.
I am not sure what exactly the encoder performs, if this is only image
transport from dispc to panel CDF pipeline in both cases should look like:
dispc ----> panel
The only difference is that panels will be connected via different Linux bus
adapters, but it will be irrelevant to CDF itself. In this case I would say
this is DSI-master rather than encoder, or at least that the only
function of the
encoder is DSI.

If display_timings on input and output differs, I suppose it should be
modeled
as display_entity, as this is an additional functionality(not covered by
DSI standard AFAIK).
CDF in such case:
dispc ---> encoder ---> panel
In this case I would call it encoder with DSI master.

>
> Furthermore, both components could have extra processing. I know the
> external encoders sometimes do have features like scaling.
The same as above, ISP with embedded DSI.
>
>>> We still have two different endpoint configurations for the same
>>> DSI-master port. If that configuration is in the DSI-master's port node,
>>> not inside an endpoint data, then that can't be supported.
>> I am not sure if I understand it correctly. But it seems quite simple:
>> when panel starts/resumes it request DSI (via control bus) to fulfill
>> its configuration settings.
>> Of course there are some settings which are not panel dependent and those
>> should reside in DSI node.
> Exactly. And when the two panels require different non-panel-dependent
> settings, how do you represent them in the DT data?

non-panel-dependent setting cannot depend on panel, by definition :)
>
>>>> We say then: callee handles locking :)
>>> Sure, but my point was that the caller handling the locking is much
>>> simpler than the callee handling locking. And the latter causes
>>> atomicity issues, as the other API could be invoked in between two calls
>>> for the first API.
>>>
>>>     
>> Could you describe such scenario?
> If we have two independent APIs, ctrl and video, that affect the same
> underlying hardware, the DSI bus, we could have a scenario like this:
>
> thread 1:
>
> ctrl->op_foo();
> ctrl->op_bar();
>
> thread 2:
>
> video->op_baz();
>
> Even if all those ops do locking properly internally, the fact that
> op_baz() can be called in between op_foo() and op_bar() may cause problems.
>
> To avoid that issue with two APIs we'd need something like:
>
> thread 1:
>
> ctrl->lock();
> ctrl->op_foo();
> ctrl->op_bar();
> ctrl->unlock();
>
> thread 2:
>
> video->lock();
> video->op_baz();
> video->unlock();
I should mention I was asking for real hw/drivers configuration.
I do not know what do you mean with video->op_baz() ?
DSI-master is not modeled in CDF, and only CDF provides video
operations.

I guess one scenario, when two panels are connected to single DSI-master.
In such case both can call DSI ops, but I do not know how do you want to
prevent it in case of your CDF-T implementation.

>
>>>> Platform devices
>>>> ~~~~~~~~~~~~~~~~
>>>> Platform devices are devices that typically appear as autonomous
>>>> entities in the system. This includes legacy port-based devices and
>>>> host bridges to peripheral buses, and most controllers integrated
>>>> into system-on-chip platforms.  What they usually have in common
>>>> is direct addressing from a CPU bus.  Rarely, a platform_device will
>>>> be connected through a segment of some other kind of bus; but its
>>>> registers will still be directly addressable.
>>> Yep, "typically" and "rarely" =). I agree, it's not clear. I think there
>>> are things with DBI/DSI that clearly point to a platform device, but
>>> also the other way.
>> Just to be sure, we are talking here about DSI-slaves, ie. for example
>> about panels,
>> where direct accessing from CPU bus usually is not possible.
> Yes. My point is that with DBI/DSI there's not much bus there (if a
> normal bus would be PCI/USB/i2c etc), it's just a point to point link
> without probing or a clearly specified setup sequence.

This is why I considered replacing DSI bus with DSI-master as parent
device and panel as slave platorm_device, like in MFD devices.

>
> If DSI/DBI was used only for control, a linux bus would probably make
> sense. But DSI/DBI is mainly a video transport channel, with the
> control-part being "secondary".
>
> And when considering that the video and control data are sent over the
> same channel (i.e. there's no separate, independent ctrl channel), and
> the strict timing restrictions with video, my gut feeling is just that
> all the extra complexity brought with separating the control to a
> separate bus is not worth it.
There is additional complexity due to bus implementation requirements
(I would rather call it boiler-plate code), but in core it is still a
matter of ops.
With Linux bus those ops are available only to DSI-slave, which is
also a good thing I guess.

Andrzej

>
>  Tomi
>
>


^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
@ 2013-10-17 12:26                         ` Andrzej Hajda
  0 siblings, 0 replies; 83+ messages in thread
From: Andrzej Hajda @ 2013-10-17 12:26 UTC (permalink / raw)
  To: Tomi Valkeinen, Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

On 10/17/2013 10:18 AM, Tomi Valkeinen wrote:
> On 17/10/13 10:48, Andrzej Hajda wrote:
>
>> The main function of DSI is to transport pixels from one IP to another IP
>> and this function IMO should not be modeled by display entity.
>> "Power, clocks, etc" will be performed via control bus according to
>> panel demands.
>> If 'DSI chip' has additional functions for video processing they can
>> be modeled by CDF entity if it makes sense.
> Now I don't follow. What do you mean with "display entity" and with "CDF
> entity"? Are they the same?
Yes, they are the same, sorry for confusion.
>
> Let me try to clarify my point:
>
> On OMAP SoC we have a DSI encoder, which takes input from the display
> controller in parallel RGB format, and outputs DSI.
>
> Then there are external encoders that take MIPI DPI as input, and output
> DSI.
>
> The only difference with the above two components is that the first one
> is embedded into the SoC. I see no reason to represent them in different
> ways (i.e. as you suggested, not representing the SoC's DSI at all).
>
> Also, if you use DSI burst mode, you will have to have different video
> timings in the DSI encoder's input and output. And depending on the
> buffering of the DSI encoder, you could have different timings in any case.
I am not sure what exactly the encoder performs, if this is only image
transport from dispc to panel CDF pipeline in both cases should look like:
dispc ----> panel
The only difference is that panels will be connected via different Linux bus
adapters, but it will be irrelevant to CDF itself. In this case I would say
this is DSI-master rather than encoder, or at least that the only
function of the
encoder is DSI.

If display_timings on input and output differs, I suppose it should be
modeled
as display_entity, as this is an additional functionality(not covered by
DSI standard AFAIK).
CDF in such case:
dispc ---> encoder ---> panel
In this case I would call it encoder with DSI master.

>
> Furthermore, both components could have extra processing. I know the
> external encoders sometimes do have features like scaling.
The same as above, ISP with embedded DSI.
>
>>> We still have two different endpoint configurations for the same
>>> DSI-master port. If that configuration is in the DSI-master's port node,
>>> not inside an endpoint data, then that can't be supported.
>> I am not sure if I understand it correctly. But it seems quite simple:
>> when panel starts/resumes it request DSI (via control bus) to fulfill
>> its configuration settings.
>> Of course there are some settings which are not panel dependent and those
>> should reside in DSI node.
> Exactly. And when the two panels require different non-panel-dependent
> settings, how do you represent them in the DT data?

non-panel-dependent setting cannot depend on panel, by definition :)
>
>>>> We say then: callee handles locking :)
>>> Sure, but my point was that the caller handling the locking is much
>>> simpler than the callee handling locking. And the latter causes
>>> atomicity issues, as the other API could be invoked in between two calls
>>> for the first API.
>>>
>>>     
>> Could you describe such scenario?
> If we have two independent APIs, ctrl and video, that affect the same
> underlying hardware, the DSI bus, we could have a scenario like this:
>
> thread 1:
>
> ctrl->op_foo();
> ctrl->op_bar();
>
> thread 2:
>
> video->op_baz();
>
> Even if all those ops do locking properly internally, the fact that
> op_baz() can be called in between op_foo() and op_bar() may cause problems.
>
> To avoid that issue with two APIs we'd need something like:
>
> thread 1:
>
> ctrl->lock();
> ctrl->op_foo();
> ctrl->op_bar();
> ctrl->unlock();
>
> thread 2:
>
> video->lock();
> video->op_baz();
> video->unlock();
I should mention I was asking for real hw/drivers configuration.
I do not know what do you mean with video->op_baz() ?
DSI-master is not modeled in CDF, and only CDF provides video
operations.

I guess one scenario, when two panels are connected to single DSI-master.
In such case both can call DSI ops, but I do not know how do you want to
prevent it in case of your CDF-T implementation.

>
>>>> Platform devices
>>>> ~~~~~~~~~~~~~~~~
>>>> Platform devices are devices that typically appear as autonomous
>>>> entities in the system. This includes legacy port-based devices and
>>>> host bridges to peripheral buses, and most controllers integrated
>>>> into system-on-chip platforms.  What they usually have in common
>>>> is direct addressing from a CPU bus.  Rarely, a platform_device will
>>>> be connected through a segment of some other kind of bus; but its
>>>> registers will still be directly addressable.
>>> Yep, "typically" and "rarely" =). I agree, it's not clear. I think there
>>> are things with DBI/DSI that clearly point to a platform device, but
>>> also the other way.
>> Just to be sure, we are talking here about DSI-slaves, ie. for example
>> about panels,
>> where direct accessing from CPU bus usually is not possible.
> Yes. My point is that with DBI/DSI there's not much bus there (if a
> normal bus would be PCI/USB/i2c etc), it's just a point to point link
> without probing or a clearly specified setup sequence.

This is why I considered replacing DSI bus with DSI-master as parent
device and panel as slave platorm_device, like in MFD devices.

>
> If DSI/DBI was used only for control, a linux bus would probably make
> sense. But DSI/DBI is mainly a video transport channel, with the
> control-part being "secondary".
>
> And when considering that the video and control data are sent over the
> same channel (i.e. there's no separate, independent ctrl channel), and
> the strict timing restrictions with video, my gut feeling is just that
> all the extra complexity brought with separating the control to a
> separate bus is not worth it.
There is additional complexity due to bus implementation requirements
(I would rather call it boiler-plate code), but in core it is still a
matter of ops.
With Linux bus those ops are available only to DSI-slave, which is
also a good thing I guess.

Andrzej

>
>  Tomi
>
>


^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
  2013-10-17 12:26                         ` Andrzej Hajda
  (?)
@ 2013-10-17 12:55                           ` Tomi Valkeinen
  -1 siblings, 0 replies; 83+ messages in thread
From: Tomi Valkeinen @ 2013-10-17 12:55 UTC (permalink / raw)
  To: Andrzej Hajda, Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

[-- Attachment #1: Type: text/plain, Size: 4219 bytes --]

On 17/10/13 15:26, Andrzej Hajda wrote:

> I am not sure what exactly the encoder performs, if this is only image
> transport from dispc to panel CDF pipeline in both cases should look like:
> dispc ----> panel
> The only difference is that panels will be connected via different Linux bus
> adapters, but it will be irrelevant to CDF itself. In this case I would say
> this is DSI-master rather than encoder, or at least that the only
> function of the
> encoder is DSI.

Yes, as I said, it's up to the driver writer how he wants to use CDF. If
he doesn't see the point of representing the SoC's DSI encoder as a
separate CDF entity, nobody forces him to do that.

On OMAP, we have single DISPC with multiple parallel outputs, and a
bunch of encoder IPs (MIPI DPI, DSI, DBI, etc). Each encoder IP can be
connected to some of the DISPC's output. In this case, even if the DSI
encoder does nothing special, I see it much better to represent the DSI
encoder as a CDF entity so that the links between DISPC, DSI, and the
DSI peripherals are all there.

> If display_timings on input and output differs, I suppose it should be
> modeled
> as display_entity, as this is an additional functionality(not covered by
> DSI standard AFAIK).

Well, DSI standard is about the DSI output. Not about the encoder's
input, or the internal operation of the encoder.

>>> Of course there are some settings which are not panel dependent and those
>>> should reside in DSI node.
>> Exactly. And when the two panels require different non-panel-dependent
>> settings, how do you represent them in the DT data?
> 
> non-panel-dependent setting cannot depend on panel, by definition :)

With "non-panel-dependent" setting I meant something that is a property
of the DSI master device, but still needs to be configured differently
for each panel.

Say, pin configuration. When using panel A, the first pin of the DSI
block could be clock+. With panel B, the first pin could be clock-. This
configuration is about DSI master, but it is different for each panel.

If we have separate endpoint in the DSI master for each panel, this data
can be there. If we don't have the endpoint, as is the case with
separate control bus, where is that data?

>>> Could you describe such scenario?
>> If we have two independent APIs, ctrl and video, that affect the same
>> underlying hardware, the DSI bus, we could have a scenario like this:
>>
>> thread 1:
>>
>> ctrl->op_foo();
>> ctrl->op_bar();
>>
>> thread 2:
>>
>> video->op_baz();
>>
>> Even if all those ops do locking properly internally, the fact that
>> op_baz() can be called in between op_foo() and op_bar() may cause problems.
>>
>> To avoid that issue with two APIs we'd need something like:
>>
>> thread 1:
>>
>> ctrl->lock();
>> ctrl->op_foo();
>> ctrl->op_bar();
>> ctrl->unlock();
>>
>> thread 2:
>>
>> video->lock();
>> video->op_baz();
>> video->unlock();
> I should mention I was asking for real hw/drivers configuration.
> I do not know what do you mean with video->op_baz() ?
> DSI-master is not modeled in CDF, and only CDF provides video
> operations.

It was just an example of the additional complexity with regarding
locking when using two APIs.

The point is that if the panel driver has two pointers (i.e. API), one
for the control bus, one for the video bus, and ops on both buses affect
the same hardware, the locking is not easy.

If, on the other hand, the panel driver only has one API to use, it's
simple to require the caller to handle any locking.

> I guess one scenario, when two panels are connected to single DSI-master.
> In such case both can call DSI ops, but I do not know how do you want to
> prevent it in case of your CDF-T implementation.

No, that was not the case I was describing. This was about a single panel.

If we have two independent APIs, we need to define how locking is
managed for those APIs. Even if in practice both APIs are used by the
same driver, and the driver can manage the locking, that's not really a
valid requirement. It'd be almost the same as requiring that gpio API
cannot be called at the same time as i2c API.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
@ 2013-10-17 12:55                           ` Tomi Valkeinen
  0 siblings, 0 replies; 83+ messages in thread
From: Tomi Valkeinen @ 2013-10-17 12:55 UTC (permalink / raw)
  To: Andrzej Hajda, Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

[-- Attachment #1: Type: text/plain, Size: 4219 bytes --]

On 17/10/13 15:26, Andrzej Hajda wrote:

> I am not sure what exactly the encoder performs, if this is only image
> transport from dispc to panel CDF pipeline in both cases should look like:
> dispc ----> panel
> The only difference is that panels will be connected via different Linux bus
> adapters, but it will be irrelevant to CDF itself. In this case I would say
> this is DSI-master rather than encoder, or at least that the only
> function of the
> encoder is DSI.

Yes, as I said, it's up to the driver writer how he wants to use CDF. If
he doesn't see the point of representing the SoC's DSI encoder as a
separate CDF entity, nobody forces him to do that.

On OMAP, we have single DISPC with multiple parallel outputs, and a
bunch of encoder IPs (MIPI DPI, DSI, DBI, etc). Each encoder IP can be
connected to some of the DISPC's output. In this case, even if the DSI
encoder does nothing special, I see it much better to represent the DSI
encoder as a CDF entity so that the links between DISPC, DSI, and the
DSI peripherals are all there.

> If display_timings on input and output differs, I suppose it should be
> modeled
> as display_entity, as this is an additional functionality(not covered by
> DSI standard AFAIK).

Well, DSI standard is about the DSI output. Not about the encoder's
input, or the internal operation of the encoder.

>>> Of course there are some settings which are not panel dependent and those
>>> should reside in DSI node.
>> Exactly. And when the two panels require different non-panel-dependent
>> settings, how do you represent them in the DT data?
> 
> non-panel-dependent setting cannot depend on panel, by definition :)

With "non-panel-dependent" setting I meant something that is a property
of the DSI master device, but still needs to be configured differently
for each panel.

Say, pin configuration. When using panel A, the first pin of the DSI
block could be clock+. With panel B, the first pin could be clock-. This
configuration is about DSI master, but it is different for each panel.

If we have separate endpoint in the DSI master for each panel, this data
can be there. If we don't have the endpoint, as is the case with
separate control bus, where is that data?

>>> Could you describe such scenario?
>> If we have two independent APIs, ctrl and video, that affect the same
>> underlying hardware, the DSI bus, we could have a scenario like this:
>>
>> thread 1:
>>
>> ctrl->op_foo();
>> ctrl->op_bar();
>>
>> thread 2:
>>
>> video->op_baz();
>>
>> Even if all those ops do locking properly internally, the fact that
>> op_baz() can be called in between op_foo() and op_bar() may cause problems.
>>
>> To avoid that issue with two APIs we'd need something like:
>>
>> thread 1:
>>
>> ctrl->lock();
>> ctrl->op_foo();
>> ctrl->op_bar();
>> ctrl->unlock();
>>
>> thread 2:
>>
>> video->lock();
>> video->op_baz();
>> video->unlock();
> I should mention I was asking for real hw/drivers configuration.
> I do not know what do you mean with video->op_baz() ?
> DSI-master is not modeled in CDF, and only CDF provides video
> operations.

It was just an example of the additional complexity with regarding
locking when using two APIs.

The point is that if the panel driver has two pointers (i.e. API), one
for the control bus, one for the video bus, and ops on both buses affect
the same hardware, the locking is not easy.

If, on the other hand, the panel driver only has one API to use, it's
simple to require the caller to handle any locking.

> I guess one scenario, when two panels are connected to single DSI-master.
> In such case both can call DSI ops, but I do not know how do you want to
> prevent it in case of your CDF-T implementation.

No, that was not the case I was describing. This was about a single panel.

If we have two independent APIs, we need to define how locking is
managed for those APIs. Even if in practice both APIs are used by the
same driver, and the driver can manage the locking, that's not really a
valid requirement. It'd be almost the same as requiring that gpio API
cannot be called at the same time as i2c API.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
@ 2013-10-17 12:55                           ` Tomi Valkeinen
  0 siblings, 0 replies; 83+ messages in thread
From: Tomi Valkeinen @ 2013-10-17 12:55 UTC (permalink / raw)
  To: Andrzej Hajda, Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

[-- Attachment #1: Type: text/plain, Size: 4219 bytes --]

On 17/10/13 15:26, Andrzej Hajda wrote:

> I am not sure what exactly the encoder performs, if this is only image
> transport from dispc to panel CDF pipeline in both cases should look like:
> dispc ----> panel
> The only difference is that panels will be connected via different Linux bus
> adapters, but it will be irrelevant to CDF itself. In this case I would say
> this is DSI-master rather than encoder, or at least that the only
> function of the
> encoder is DSI.

Yes, as I said, it's up to the driver writer how he wants to use CDF. If
he doesn't see the point of representing the SoC's DSI encoder as a
separate CDF entity, nobody forces him to do that.

On OMAP, we have single DISPC with multiple parallel outputs, and a
bunch of encoder IPs (MIPI DPI, DSI, DBI, etc). Each encoder IP can be
connected to some of the DISPC's output. In this case, even if the DSI
encoder does nothing special, I see it much better to represent the DSI
encoder as a CDF entity so that the links between DISPC, DSI, and the
DSI peripherals are all there.

> If display_timings on input and output differs, I suppose it should be
> modeled
> as display_entity, as this is an additional functionality(not covered by
> DSI standard AFAIK).

Well, DSI standard is about the DSI output. Not about the encoder's
input, or the internal operation of the encoder.

>>> Of course there are some settings which are not panel dependent and those
>>> should reside in DSI node.
>> Exactly. And when the two panels require different non-panel-dependent
>> settings, how do you represent them in the DT data?
> 
> non-panel-dependent setting cannot depend on panel, by definition :)

With "non-panel-dependent" setting I meant something that is a property
of the DSI master device, but still needs to be configured differently
for each panel.

Say, pin configuration. When using panel A, the first pin of the DSI
block could be clock+. With panel B, the first pin could be clock-. This
configuration is about DSI master, but it is different for each panel.

If we have separate endpoint in the DSI master for each panel, this data
can be there. If we don't have the endpoint, as is the case with
separate control bus, where is that data?

>>> Could you describe such scenario?
>> If we have two independent APIs, ctrl and video, that affect the same
>> underlying hardware, the DSI bus, we could have a scenario like this:
>>
>> thread 1:
>>
>> ctrl->op_foo();
>> ctrl->op_bar();
>>
>> thread 2:
>>
>> video->op_baz();
>>
>> Even if all those ops do locking properly internally, the fact that
>> op_baz() can be called in between op_foo() and op_bar() may cause problems.
>>
>> To avoid that issue with two APIs we'd need something like:
>>
>> thread 1:
>>
>> ctrl->lock();
>> ctrl->op_foo();
>> ctrl->op_bar();
>> ctrl->unlock();
>>
>> thread 2:
>>
>> video->lock();
>> video->op_baz();
>> video->unlock();
> I should mention I was asking for real hw/drivers configuration.
> I do not know what do you mean with video->op_baz() ?
> DSI-master is not modeled in CDF, and only CDF provides video
> operations.

It was just an example of the additional complexity with regarding
locking when using two APIs.

The point is that if the panel driver has two pointers (i.e. API), one
for the control bus, one for the video bus, and ops on both buses affect
the same hardware, the locking is not easy.

If, on the other hand, the panel driver only has one API to use, it's
simple to require the caller to handle any locking.

> I guess one scenario, when two panels are connected to single DSI-master.
> In such case both can call DSI ops, but I do not know how do you want to
> prevent it in case of your CDF-T implementation.

No, that was not the case I was describing. This was about a single panel.

If we have two independent APIs, we need to define how locking is
managed for those APIs. Even if in practice both APIs are used by the
same driver, and the driver can manage the locking, that's not really a
valid requirement. It'd be almost the same as requiring that gpio API
cannot be called at the same time as i2c API.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 901 bytes --]

^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
  2013-10-17 12:55                           ` Tomi Valkeinen
@ 2013-10-18 11:55                             ` Andrzej Hajda
  -1 siblings, 0 replies; 83+ messages in thread
From: Andrzej Hajda @ 2013-10-18 11:55 UTC (permalink / raw)
  To: Tomi Valkeinen, Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

On 10/17/2013 02:55 PM, Tomi Valkeinen wrote:
> On 17/10/13 15:26, Andrzej Hajda wrote:
>
>> I am not sure what exactly the encoder performs, if this is only image
>> transport from dispc to panel CDF pipeline in both cases should look like:
>> dispc ----> panel
>> The only difference is that panels will be connected via different Linux bus
>> adapters, but it will be irrelevant to CDF itself. In this case I would say
>> this is DSI-master rather than encoder, or at least that the only
>> function of the
>> encoder is DSI.
> Yes, as I said, it's up to the driver writer how he wants to use CDF. If
> he doesn't see the point of representing the SoC's DSI encoder as a
> separate CDF entity, nobody forces him to do that.
Having it as an entity would cause the 'problem' of two APIs as you
described below :)
One API via control bus, another one via CDF.
>
> On OMAP, we have single DISPC with multiple parallel outputs, and a
> bunch of encoder IPs (MIPI DPI, DSI, DBI, etc). Each encoder IP can be
> connected to some of the DISPC's output. In this case, even if the DSI
> encoder does nothing special, I see it much better to represent the DSI
> encoder as a CDF entity so that the links between DISPC, DSI, and the
> DSI peripherals are all there.
>
>> If display_timings on input and output differs, I suppose it should be
>> modeled
>> as display_entity, as this is an additional functionality(not covered by
>> DSI standard AFAIK).
> Well, DSI standard is about the DSI output. Not about the encoder's
> input, or the internal operation of the encoder.
>
>>>> Of course there are some settings which are not panel dependent and those
>>>> should reside in DSI node.
>>> Exactly. And when the two panels require different non-panel-dependent
>>> settings, how do you represent them in the DT data?
>> non-panel-dependent setting cannot depend on panel, by definition :)
> With "non-panel-dependent" setting I meant something that is a property
> of the DSI master device, but still needs to be configured differently
> for each panel.
>
> Say, pin configuration. When using panel A, the first pin of the DSI
> block could be clock+. With panel B, the first pin could be clock-. This
> configuration is about DSI master, but it is different for each panel.
>
> If we have separate endpoint in the DSI master for each panel, this data
> can be there. If we don't have the endpoint, as is the case with
> separate control bus, where is that data?
I am open to propositions. For me it seems somehow similar to clock mapping
in DT (clock-names are mapped to provider clocks), so I think it could
be put in panel node and it will be parsed by DSI-master.
>
>>>> Could you describe such scenario?
>>> If we have two independent APIs, ctrl and video, that affect the same
>>> underlying hardware, the DSI bus, we could have a scenario like this:
>>>
>>> thread 1:
>>>
>>> ctrl->op_foo();
>>> ctrl->op_bar();
>>>
>>> thread 2:
>>>
>>> video->op_baz();
>>>
>>> Even if all those ops do locking properly internally, the fact that
>>> op_baz() can be called in between op_foo() and op_bar() may cause problems.
>>>
>>> To avoid that issue with two APIs we'd need something like:
>>>
>>> thread 1:
>>>
>>> ctrl->lock();
>>> ctrl->op_foo();
>>> ctrl->op_bar();
>>> ctrl->unlock();
>>>
>>> thread 2:
>>>
>>> video->lock();
>>> video->op_baz();
>>> video->unlock();
>> I should mention I was asking for real hw/drivers configuration.
>> I do not know what do you mean with video->op_baz() ?
>> DSI-master is not modeled in CDF, and only CDF provides video
>> operations.
> It was just an example of the additional complexity with regarding
> locking when using two APIs.
>
> The point is that if the panel driver has two pointers (i.e. API), one
> for the control bus, one for the video bus, and ops on both buses affect
> the same hardware, the locking is not easy.
>
> If, on the other hand, the panel driver only has one API to use, it's
> simple to require the caller to handle any locking.
I guess you are describing scenario with DSI-master having its own entity.
In such case its video ops are accessible at least to all pipeline
neightbourgs and
to pipeline controler, so I do not see how the client side locking would
work anyway.
Additionally multiple panels connected to one DSI also makes it harder.
Thus I do not see that 'client lock' apporach would work anyway, even
using video-source approach.

Andrzej



^ permalink raw reply	[flat|nested] 83+ messages in thread

* Re: [PATCH/RFC v3 00/19] Common Display Framework
@ 2013-10-18 11:55                             ` Andrzej Hajda
  0 siblings, 0 replies; 83+ messages in thread
From: Andrzej Hajda @ 2013-10-18 11:55 UTC (permalink / raw)
  To: Tomi Valkeinen, Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Jesse Barnes, Benjamin Gaignard,
	Tom Gall, Kyungmin Park, linux-media, Stephen Warren, Mark Zhang,
	Alexandre Courbot, Ragesh Radhakrishnan, Thomas Petazzoni,
	Sunil Joshi, Maxime Ripard, Vikas Sajjan, Marcus Lorentzon

On 10/17/2013 02:55 PM, Tomi Valkeinen wrote:
> On 17/10/13 15:26, Andrzej Hajda wrote:
>
>> I am not sure what exactly the encoder performs, if this is only image
>> transport from dispc to panel CDF pipeline in both cases should look like:
>> dispc ----> panel
>> The only difference is that panels will be connected via different Linux bus
>> adapters, but it will be irrelevant to CDF itself. In this case I would say
>> this is DSI-master rather than encoder, or at least that the only
>> function of the
>> encoder is DSI.
> Yes, as I said, it's up to the driver writer how he wants to use CDF. If
> he doesn't see the point of representing the SoC's DSI encoder as a
> separate CDF entity, nobody forces him to do that.
Having it as an entity would cause the 'problem' of two APIs as you
described below :)
One API via control bus, another one via CDF.
>
> On OMAP, we have single DISPC with multiple parallel outputs, and a
> bunch of encoder IPs (MIPI DPI, DSI, DBI, etc). Each encoder IP can be
> connected to some of the DISPC's output. In this case, even if the DSI
> encoder does nothing special, I see it much better to represent the DSI
> encoder as a CDF entity so that the links between DISPC, DSI, and the
> DSI peripherals are all there.
>
>> If display_timings on input and output differs, I suppose it should be
>> modeled
>> as display_entity, as this is an additional functionality(not covered by
>> DSI standard AFAIK).
> Well, DSI standard is about the DSI output. Not about the encoder's
> input, or the internal operation of the encoder.
>
>>>> Of course there are some settings which are not panel dependent and those
>>>> should reside in DSI node.
>>> Exactly. And when the two panels require different non-panel-dependent
>>> settings, how do you represent them in the DT data?
>> non-panel-dependent setting cannot depend on panel, by definition :)
> With "non-panel-dependent" setting I meant something that is a property
> of the DSI master device, but still needs to be configured differently
> for each panel.
>
> Say, pin configuration. When using panel A, the first pin of the DSI
> block could be clock+. With panel B, the first pin could be clock-. This
> configuration is about DSI master, but it is different for each panel.
>
> If we have separate endpoint in the DSI master for each panel, this data
> can be there. If we don't have the endpoint, as is the case with
> separate control bus, where is that data?
I am open to propositions. For me it seems somehow similar to clock mapping
in DT (clock-names are mapped to provider clocks), so I think it could
be put in panel node and it will be parsed by DSI-master.
>
>>>> Could you describe such scenario?
>>> If we have two independent APIs, ctrl and video, that affect the same
>>> underlying hardware, the DSI bus, we could have a scenario like this:
>>>
>>> thread 1:
>>>
>>> ctrl->op_foo();
>>> ctrl->op_bar();
>>>
>>> thread 2:
>>>
>>> video->op_baz();
>>>
>>> Even if all those ops do locking properly internally, the fact that
>>> op_baz() can be called in between op_foo() and op_bar() may cause problems.
>>>
>>> To avoid that issue with two APIs we'd need something like:
>>>
>>> thread 1:
>>>
>>> ctrl->lock();
>>> ctrl->op_foo();
>>> ctrl->op_bar();
>>> ctrl->unlock();
>>>
>>> thread 2:
>>>
>>> video->lock();
>>> video->op_baz();
>>> video->unlock();
>> I should mention I was asking for real hw/drivers configuration.
>> I do not know what do you mean with video->op_baz() ?
>> DSI-master is not modeled in CDF, and only CDF provides video
>> operations.
> It was just an example of the additional complexity with regarding
> locking when using two APIs.
>
> The point is that if the panel driver has two pointers (i.e. API), one
> for the control bus, one for the video bus, and ops on both buses affect
> the same hardware, the locking is not easy.
>
> If, on the other hand, the panel driver only has one API to use, it's
> simple to require the caller to handle any locking.
I guess you are describing scenario with DSI-master having its own entity.
In such case its video ops are accessible at least to all pipeline
neightbourgs and
to pipeline controler, so I do not see how the client side locking would
work anyway.
Additionally multiple panels connected to one DSI also makes it harder.
Thus I do not see that 'client lock' apporach would work anyway, even
using video-source approach.

Andrzej



^ permalink raw reply	[flat|nested] 83+ messages in thread

* [PATCH/RFC v3 07/19] video: display: Add pixel coding definitions
  2013-08-09 23:02 Laurent Pinchart
@ 2013-08-09 23:03   ` Laurent Pinchart
  0 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2013-08-09 23:03 UTC (permalink / raw)
  To: dri-devel, linux-fbdev, linux-media

Pixel codings describe how pixels are transmitted on a physical bus. The
information can be communicated between drivers to configure devices.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 include/video/display.h | 120 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 120 insertions(+)

diff --git a/include/video/display.h b/include/video/display.h
index 36ff637..ba319d6 100644
--- a/include/video/display.h
+++ b/include/video/display.h
@@ -18,6 +18,126 @@
 #include <linux/module.h>
 #include <media/media-entity.h>
 
+#define DISPLAY_PIXEL_CODING(option, type, from, to, variant) \
+	(((option) << 17) | ((type) << 13) | ((variant) << 10) | \
+	 ((to) << 5) | (from))
+
+#define DISPLAY_PIXEL_CODING_FROM(coding)	((coding) & 0x1f)
+#define DISPLAY_PIXEL_CODING_TO(coding)		(((coding) >> 5) & 0x1f)
+#define DISPLAY_PIXEL_CODING_VARIANT(coding)	(((coding) >> 10) & 7)
+#define DISPLAY_PIXEL_CODING_TYPE(coding)	(((coding) >> 13) & 0xf)
+
+#define DISPLAY_PIXEL_CODING_TYPE_DBI	0
+#define DISPLAY_PIXEL_CODING_TYPE_DPI	1
+
+/* DBI pixel codings. */
+#define DISPLAY_PIXEL_CODING_DBI(from, to, variant) \
+	DISPLAY_PIXEL_CODING_TYPE(DISPLAY_PIXEL_CODING_TYPE_DBI, \
+				  from, to, variant, 0)
+
+/* Standard DBI codings, defined in the DBI specification. */
+/*   17   16   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1    0 */
+/*    -    -    -    -    -    -    -    -    -    - R0,2 R0,1 R0,0 G0,2 G0,1 G0,0 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_8TO8		DISPLAY_PIXEL_CODING_DBI(8, 8, 0)
+/*    -    -    -    -    -    -    -    -    -    - R0,3 R0,2 R0,1 R0,0 G0,3 G0,2 G0,1 G0,0 */
+/*    -    -    -    -    -    -    -    -    -    - B0,3 B0,2 B0,1 B0,0 R1,3 R1,2 R1,1 R1,0 */
+/*    -    -    -    -    -    -    -    -    -    - G1,3 G1,2 G1,1 G1,0 B1,3 B1,2 B1,1 b1,0 */
+#define DISPLAY_PIXEL_CODING_DBI_12TO8		DISPLAY_PIXEL_CODING_DBI(12, 8, 0)
+/*    -    -    -    -    -    -    -    -    -    - R0,4 R0,3 R0,2 R0,1 R0,0 G0,5 G0,4 G0,3 */
+/*    -    -    -    -    -    -    -    -    -    - G0,2 G0,1 G0,0 B0,4 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_16TO8		DISPLAY_PIXEL_CODING_DBI(16, 8, 0)
+/*    -    -    -    -    -    -    -    -    -    - R0,5 R0,4 R0,3 R0,2 R0,1 R0,0    -    - */
+/*    -    -    -    -    -    -    -    -    -    - G0,5 G0,4 G0,3 G0,2 G0,1 G0,0    -    - */
+/*    -    -    -    -    -    -    -    -    -    - B0,5 B0,4 B0,3 B0,2 B0,1 B0,0    -    - */
+#define DISPLAY_PIXEL_CODING_DBI_18TO8		DISPLAY_PIXEL_CODING_DBI(18, 8, 0)
+/*    -    -    -    -    -    -    -    -    -    - R0,7 R0,6 R0,5 R0,4 R0,3 R0,2 R0,1 R0,0 */
+/*    -    -    -    -    -    -    -    -    -    - G0,7 G0,6 G0,5 G0,4 G0,3 G0,2 G0,1 G0,0 */
+/*    -    -    -    -    -    -    -    -    -    - B0,7 B0,6 B0,5 B0,4 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_24TO8		DISPLAY_PIXEL_CODING_DBI(24, 8, 0)
+/*    -    -    -    -    -    -    -    -    - R0,5 R0,4 R0,3 R0,2 R0,1 R0,0 G0,5 G0,4 G0,4 */
+/*    -    -    -    -    -    -    -    -    - G0,2 G0,1 G0,0 B0,5 B0,4 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_18TO9		DISPLAY_PIXEL_CODING_DBI(18, 9, 0)
+/*    -    - R1,2 R1,1 R1,0 G1,2 G1,1 G1,0 B1,1 B1,0 R0,2 R0,1 R0,0 G0,2 G0,1 G0,0 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_8TO16		DISPLAY_PIXEL_CODING_DBI(8, 16, 0)
+/*    -    -    -    -    -    - R0,3 R0,2 R0,1 R0,0 G0,3 G0,2 G0,1 G0,0 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_12TO16		DISPLAY_PIXEL_CODING_DBI(12, 16, 0)
+/*    -    - R0,4 R0,3 R0,2 R0,1 R0,0 G0,5 G0,4 G0,3 G0,2 G0,1 G0,0 B0,4 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_16TO16		DISPLAY_PIXEL_CODING_DBI(16, 16, 0)
+/*    -    - R0,5 R0,4 R0,3 R0,2 R0,1 R0,0    -    - G0,5 G0,4 G0,3 G0,2 G0,1 G0,0    -    - */
+/*    -    - B0,5 B0,4 B0,3 B0,2 B0,1 B0,0    -    - R1,5 R1,4 R1,3 R1,2 R1,1 R1,0    -    - */
+/*    -    - G1,5 G1,4 G1,3 G1,2 G1,1 G1,0    -    - B1,5 B1,4 B1,3 B1,2 B1,1 B1,0    -    - */
+#define DISPLAY_PIXEL_CODING_DBI_18TO16_A	DISPLAY_PIXEL_CODING_DBI(18, 16, 0)
+/*    -    -    -    -    -    -    -    -    -    - R0,5 R0,4 R0,3 R0,2 R0,1 R0,0    -    - */
+/*    -    - G0,5 G0,4 G0,3 G0,2 G0,1 G0,0    -    - B0,5 B0,4 B0,3 B0,2 B0,1 B0,0    -    - */
+#define DISPLAY_PIXEL_CODING_DBI_18TO16_B	DISPLAY_PIXEL_CODING_DBI(18, 16, 1)
+/*    -    - R0,7 R0,6 R0,5 R0,4 R0,3 R0,2 R0,1 R0,0 G0,7 G0,6 G0,5 G0,4 G0,3 G0,2 G0,1 G0,0 */
+/*    -    - B0,7 B0,6 B0,5 B0,4 B0,3 B0,2 B0,1 B0,0 R1,7 R1,6 R1,5 R1,4 R1,3 R1,2 R1,1 R1,0 */
+/*    -    - G1,7 G1,6 G1,5 G1,4 G1,3 G1,2 G1,1 G1,0 B1,7 B1,6 B1,5 B1,4 B1,3 B1,2 B1,1 B1,0 */
+#define DISPLAY_PIXEL_CODING_DBI_24TO16_A	DISPLAY_PIXEL_CODING_DBI(24, 16, 0)
+/*    -    -    -    -    -    -    -    -    -    - R0,7 R0,6 R0,5 R0,4 R0,3 R0,2 R0,1 R0,0 */
+/*    -    - G0,7 G0,6 G0,5 G0,4 G0,3 G0,2 G0,1 G0,0 B0,7 B0,6 B0,5 B0,4 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_24TO16_B	DISPLAY_PIXEL_CODING_DBI(24, 16, 1)
+
+/* Non-standard DBI pixel codings. */
+/*   17   16   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1    0 */
+/*    -    -    -    -    -    -    -    -    -    - R0,5 R0,4 R0,3 R0,2 R0,1 R0,0 G0,5 G0,4 */
+/*    -    -    -    -    -    -    -    -    -    - G0,3 G0,2 G0,1 G0,0 B0,5 B0,4 B0,3 B0,2 */
+/*    -    -    -    -    -    -    -    -    -    -    -    -    -    -    -    - B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_18TO8_B	DISPLAY_PIXEL_CODING_DBI(18, 8, 1)
+/*    -    -    -    -    -    -    -    -    -    -    -    -    -    -    -    - R0,5 R0,4 */
+/*    -    -    -    -    -    -    -    -    -    - R0,3 R0,2 R0,1 R0,0 G0,5 G0,4 G0,3 G0,2 */
+/*    -    -    -    -    -    -    -    -    -    - G0,1 G0,0 B0,5 B0,4 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_18TO8_C	DISPLAY_PIXEL_CODING_DBI(18, 8, 2)
+/*    -    - R0,5 R0,4 R0,3 R0,2 R0,1 R0,0 G0,5 G0,4 G0,3 G0,2 G0,1 G0,0 B0,5 B0,4 B0,3 B0,2 */
+/*    -    - B0,1 B0,0    -    -    -    -    -    -    -    -    -    -    -    -    -    - */
+#define DISPLAY_PIXEL_CODING_DBI_18TO16_C	DISPLAY_PIXEL_CODING_DBI(18, 16, 2)
+/*    -    - R0,5 R0,4    -    -    -    -    -    -    -    -    -    -    -    -    -    - */
+/*    -    - R0,3 R0,2 R0,1 R0,0 G0,5 G0,4 G0,3 G0,2 G0,1 G0,0 B0,5 B0,4 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_18TO16_D	DISPLAY_PIXEL_CODING_DBI(18, 16, 3)
+/*    -    -    -    -    -    - R0,7 R0,6 R0,5 R0,4 R0,3 R0,2 R0,1 R0,0 G0,7 G0,6 G0,5 G0,4 */
+/*    -    -    -    -    -    - G0,3 G0,2 G0,1 G0,0 B0,7 B0,6 B0,5 B0,4 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_24TO12		DISPLAY_PIXEL_CODING_DBI(24, 12, 0)
+/* R0,5 R0,4 R0,3 R0,2 R0,1 R0,0 G0,5 G0,4 G0,3 G0,2 G0,1 G0,0 B0,5 B0,4 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_18TO18		DISPLAY_PIXEL_CODING_DBI(18, 18, 0)
+
+/* DPI pixel codings. */
+#define DISPLAY_PIXEL_CODING_DPI_RGB(from, to, variant) \
+	DISPLAY_PIXEL_CODING_TYPE(DISPLAY_PIXEL_CODING_TYPE_DPI, \
+				  from, to, variant, 0)
+#define DISPLAY_PIXEL_CODING_DPI_YUV(from, to, variant) \
+	DISPLAY_PIXEL_CODING_TYPE(DISPLAY_PIXEL_CODING_TYPE_DPI, \
+				  from, to, variant, 1)
+
+/* Standard DPI codings, defined in the DPI specification. */
+/* 23 22 21 20 19 28 17 16 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0 */
+/*  -  -  -  -  -  -  -  - R4 R3 R2 R1 R0 G5 G4 G3 G2 G1 G0 B4 B3 B2 B1 B0 */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_16TO16	DISPLAY_PIXEL_CODING_DPI_RGB(16, 16, 0)
+/*  -  -  -  -  -  - R5 R4 R3 R2 R1 R0 G5 G4 G3 G2 G1 G0 B5 B4 B3 B2 B1 B0 */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_18TO18	DISPLAY_PIXEL_CODING_DPI_RGB(18, 18, 0)
+/*  -  -  - R4 R3 R2 R1 R0  -  - G5 G4 G3 G2 G1 G0  -  -  - B4 B3 B2 B1 B0 */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_16TO20	DISPLAY_PIXEL_CODING_DPI_RGB(16, 20, 0)
+/*  -  - R4 R3 R2 R1 R0  -  -  - G5 G4 G3 G2 G1 G0  -  - B4 B3 B2 B1 B0  - */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_16TO22	DISPLAY_PIXEL_CODING_DPI_RGB(16, 22, 0)
+/*  -  - R5 R4 R3 R2 R1 R0  -  - G5 G4 G3 G2 G1 G0  -  - B5 B4 B3 B2 B1 B0 */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_18TO22	DISPLAY_PIXEL_CODING_DPI_RGB(18, 22, 0)
+/* R7 R6 R5 R4 R3 R2 R1 R0 G7 G6 G5 G4 G3 G2 G1 G0 B7 B6 B5 B4 B3 B2 B1 B0 */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_24TO24	DISPLAY_PIXEL_CODING_DPI_RGB(24, 24, 0)
+
+/* Non-standard DPI pixel codings. */
+/* 23 22 21 20 19 28 17 16 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0 */
+/*  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - R7 R6 R5 R4 R3 R2 R1 R0 */
+/*  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - G7 G6 G5 G4 G3 G2 G1 G0 */
+/*  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - B7 B6 B5 B4 B3 B2 B1 B0 */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_24TO8	DISPLAY_PIXEL_CODING_DPI_RGB(24, 8, 0)
+/*  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - R5 R4 R3 R2 R1 R0 G5 G4 G3 */
+/*  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - G2 G1 G0 B5 B4 B3 B2 B1 B0 */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_18TO9	DISPLAY_PIXEL_CODING_DPI_RGB(18, 9, 0)
+/*  -  -  -  -  -  -  -  -  -  -  -  - R3 R2 R1 R0 G3 G2 G1 G0 B3 B2 B1 B0 */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_12TO12	DISPLAY_PIXEL_CODING_DPI_RGB(12, 12, 0)
+/*  -  -  -  -  -  -  -  -  -  -  -  - R7 R6 R5 R4 R3 R2 R1 R0 G7 G6 G5 G4 */
+/*  -  -  -  -  -  -  -  -  -  -  -  - G3 G2 G1 G0 B7 B6 B5 B4 B3 B2 B1 B0 */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_24TO12	DISPLAY_PIXEL_CODING_DPI_RGB(24, 12, 0)
+
 /* -----------------------------------------------------------------------------
  * Display Entity
  */
-- 
1.8.1.5


^ permalink raw reply related	[flat|nested] 83+ messages in thread

* [PATCH/RFC v3 07/19] video: display: Add pixel coding definitions
@ 2013-08-09 23:03   ` Laurent Pinchart
  0 siblings, 0 replies; 83+ messages in thread
From: Laurent Pinchart @ 2013-08-09 23:03 UTC (permalink / raw)
  To: dri-devel, linux-fbdev, linux-media

Pixel codings describe how pixels are transmitted on a physical bus. The
information can be communicated between drivers to configure devices.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 include/video/display.h | 120 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 120 insertions(+)

diff --git a/include/video/display.h b/include/video/display.h
index 36ff637..ba319d6 100644
--- a/include/video/display.h
+++ b/include/video/display.h
@@ -18,6 +18,126 @@
 #include <linux/module.h>
 #include <media/media-entity.h>
 
+#define DISPLAY_PIXEL_CODING(option, type, from, to, variant) \
+	(((option) << 17) | ((type) << 13) | ((variant) << 10) | \
+	 ((to) << 5) | (from))
+
+#define DISPLAY_PIXEL_CODING_FROM(coding)	((coding) & 0x1f)
+#define DISPLAY_PIXEL_CODING_TO(coding)		(((coding) >> 5) & 0x1f)
+#define DISPLAY_PIXEL_CODING_VARIANT(coding)	(((coding) >> 10) & 7)
+#define DISPLAY_PIXEL_CODING_TYPE(coding)	(((coding) >> 13) & 0xf)
+
+#define DISPLAY_PIXEL_CODING_TYPE_DBI	0
+#define DISPLAY_PIXEL_CODING_TYPE_DPI	1
+
+/* DBI pixel codings. */
+#define DISPLAY_PIXEL_CODING_DBI(from, to, variant) \
+	DISPLAY_PIXEL_CODING_TYPE(DISPLAY_PIXEL_CODING_TYPE_DBI, \
+				  from, to, variant, 0)
+
+/* Standard DBI codings, defined in the DBI specification. */
+/*   17   16   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1    0 */
+/*    -    -    -    -    -    -    -    -    -    - R0,2 R0,1 R0,0 G0,2 G0,1 G0,0 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_8TO8		DISPLAY_PIXEL_CODING_DBI(8, 8, 0)
+/*    -    -    -    -    -    -    -    -    -    - R0,3 R0,2 R0,1 R0,0 G0,3 G0,2 G0,1 G0,0 */
+/*    -    -    -    -    -    -    -    -    -    - B0,3 B0,2 B0,1 B0,0 R1,3 R1,2 R1,1 R1,0 */
+/*    -    -    -    -    -    -    -    -    -    - G1,3 G1,2 G1,1 G1,0 B1,3 B1,2 B1,1 b1,0 */
+#define DISPLAY_PIXEL_CODING_DBI_12TO8		DISPLAY_PIXEL_CODING_DBI(12, 8, 0)
+/*    -    -    -    -    -    -    -    -    -    - R0,4 R0,3 R0,2 R0,1 R0,0 G0,5 G0,4 G0,3 */
+/*    -    -    -    -    -    -    -    -    -    - G0,2 G0,1 G0,0 B0,4 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_16TO8		DISPLAY_PIXEL_CODING_DBI(16, 8, 0)
+/*    -    -    -    -    -    -    -    -    -    - R0,5 R0,4 R0,3 R0,2 R0,1 R0,0    -    - */
+/*    -    -    -    -    -    -    -    -    -    - G0,5 G0,4 G0,3 G0,2 G0,1 G0,0    -    - */
+/*    -    -    -    -    -    -    -    -    -    - B0,5 B0,4 B0,3 B0,2 B0,1 B0,0    -    - */
+#define DISPLAY_PIXEL_CODING_DBI_18TO8		DISPLAY_PIXEL_CODING_DBI(18, 8, 0)
+/*    -    -    -    -    -    -    -    -    -    - R0,7 R0,6 R0,5 R0,4 R0,3 R0,2 R0,1 R0,0 */
+/*    -    -    -    -    -    -    -    -    -    - G0,7 G0,6 G0,5 G0,4 G0,3 G0,2 G0,1 G0,0 */
+/*    -    -    -    -    -    -    -    -    -    - B0,7 B0,6 B0,5 B0,4 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_24TO8		DISPLAY_PIXEL_CODING_DBI(24, 8, 0)
+/*    -    -    -    -    -    -    -    -    - R0,5 R0,4 R0,3 R0,2 R0,1 R0,0 G0,5 G0,4 G0,4 */
+/*    -    -    -    -    -    -    -    -    - G0,2 G0,1 G0,0 B0,5 B0,4 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_18TO9		DISPLAY_PIXEL_CODING_DBI(18, 9, 0)
+/*    -    - R1,2 R1,1 R1,0 G1,2 G1,1 G1,0 B1,1 B1,0 R0,2 R0,1 R0,0 G0,2 G0,1 G0,0 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_8TO16		DISPLAY_PIXEL_CODING_DBI(8, 16, 0)
+/*    -    -    -    -    -    - R0,3 R0,2 R0,1 R0,0 G0,3 G0,2 G0,1 G0,0 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_12TO16		DISPLAY_PIXEL_CODING_DBI(12, 16, 0)
+/*    -    - R0,4 R0,3 R0,2 R0,1 R0,0 G0,5 G0,4 G0,3 G0,2 G0,1 G0,0 B0,4 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_16TO16		DISPLAY_PIXEL_CODING_DBI(16, 16, 0)
+/*    -    - R0,5 R0,4 R0,3 R0,2 R0,1 R0,0    -    - G0,5 G0,4 G0,3 G0,2 G0,1 G0,0    -    - */
+/*    -    - B0,5 B0,4 B0,3 B0,2 B0,1 B0,0    -    - R1,5 R1,4 R1,3 R1,2 R1,1 R1,0    -    - */
+/*    -    - G1,5 G1,4 G1,3 G1,2 G1,1 G1,0    -    - B1,5 B1,4 B1,3 B1,2 B1,1 B1,0    -    - */
+#define DISPLAY_PIXEL_CODING_DBI_18TO16_A	DISPLAY_PIXEL_CODING_DBI(18, 16, 0)
+/*    -    -    -    -    -    -    -    -    -    - R0,5 R0,4 R0,3 R0,2 R0,1 R0,0    -    - */
+/*    -    - G0,5 G0,4 G0,3 G0,2 G0,1 G0,0    -    - B0,5 B0,4 B0,3 B0,2 B0,1 B0,0    -    - */
+#define DISPLAY_PIXEL_CODING_DBI_18TO16_B	DISPLAY_PIXEL_CODING_DBI(18, 16, 1)
+/*    -    - R0,7 R0,6 R0,5 R0,4 R0,3 R0,2 R0,1 R0,0 G0,7 G0,6 G0,5 G0,4 G0,3 G0,2 G0,1 G0,0 */
+/*    -    - B0,7 B0,6 B0,5 B0,4 B0,3 B0,2 B0,1 B0,0 R1,7 R1,6 R1,5 R1,4 R1,3 R1,2 R1,1 R1,0 */
+/*    -    - G1,7 G1,6 G1,5 G1,4 G1,3 G1,2 G1,1 G1,0 B1,7 B1,6 B1,5 B1,4 B1,3 B1,2 B1,1 B1,0 */
+#define DISPLAY_PIXEL_CODING_DBI_24TO16_A	DISPLAY_PIXEL_CODING_DBI(24, 16, 0)
+/*    -    -    -    -    -    -    -    -    -    - R0,7 R0,6 R0,5 R0,4 R0,3 R0,2 R0,1 R0,0 */
+/*    -    - G0,7 G0,6 G0,5 G0,4 G0,3 G0,2 G0,1 G0,0 B0,7 B0,6 B0,5 B0,4 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_24TO16_B	DISPLAY_PIXEL_CODING_DBI(24, 16, 1)
+
+/* Non-standard DBI pixel codings. */
+/*   17   16   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1    0 */
+/*    -    -    -    -    -    -    -    -    -    - R0,5 R0,4 R0,3 R0,2 R0,1 R0,0 G0,5 G0,4 */
+/*    -    -    -    -    -    -    -    -    -    - G0,3 G0,2 G0,1 G0,0 B0,5 B0,4 B0,3 B0,2 */
+/*    -    -    -    -    -    -    -    -    -    -    -    -    -    -    -    - B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_18TO8_B	DISPLAY_PIXEL_CODING_DBI(18, 8, 1)
+/*    -    -    -    -    -    -    -    -    -    -    -    -    -    -    -    - R0,5 R0,4 */
+/*    -    -    -    -    -    -    -    -    -    - R0,3 R0,2 R0,1 R0,0 G0,5 G0,4 G0,3 G0,2 */
+/*    -    -    -    -    -    -    -    -    -    - G0,1 G0,0 B0,5 B0,4 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_18TO8_C	DISPLAY_PIXEL_CODING_DBI(18, 8, 2)
+/*    -    - R0,5 R0,4 R0,3 R0,2 R0,1 R0,0 G0,5 G0,4 G0,3 G0,2 G0,1 G0,0 B0,5 B0,4 B0,3 B0,2 */
+/*    -    - B0,1 B0,0    -    -    -    -    -    -    -    -    -    -    -    -    -    - */
+#define DISPLAY_PIXEL_CODING_DBI_18TO16_C	DISPLAY_PIXEL_CODING_DBI(18, 16, 2)
+/*    -    - R0,5 R0,4    -    -    -    -    -    -    -    -    -    -    -    -    -    - */
+/*    -    - R0,3 R0,2 R0,1 R0,0 G0,5 G0,4 G0,3 G0,2 G0,1 G0,0 B0,5 B0,4 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_18TO16_D	DISPLAY_PIXEL_CODING_DBI(18, 16, 3)
+/*    -    -    -    -    -    - R0,7 R0,6 R0,5 R0,4 R0,3 R0,2 R0,1 R0,0 G0,7 G0,6 G0,5 G0,4 */
+/*    -    -    -    -    -    - G0,3 G0,2 G0,1 G0,0 B0,7 B0,6 B0,5 B0,4 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_24TO12		DISPLAY_PIXEL_CODING_DBI(24, 12, 0)
+/* R0,5 R0,4 R0,3 R0,2 R0,1 R0,0 G0,5 G0,4 G0,3 G0,2 G0,1 G0,0 B0,5 B0,4 B0,3 B0,2 B0,1 B0,0 */
+#define DISPLAY_PIXEL_CODING_DBI_18TO18		DISPLAY_PIXEL_CODING_DBI(18, 18, 0)
+
+/* DPI pixel codings. */
+#define DISPLAY_PIXEL_CODING_DPI_RGB(from, to, variant) \
+	DISPLAY_PIXEL_CODING_TYPE(DISPLAY_PIXEL_CODING_TYPE_DPI, \
+				  from, to, variant, 0)
+#define DISPLAY_PIXEL_CODING_DPI_YUV(from, to, variant) \
+	DISPLAY_PIXEL_CODING_TYPE(DISPLAY_PIXEL_CODING_TYPE_DPI, \
+				  from, to, variant, 1)
+
+/* Standard DPI codings, defined in the DPI specification. */
+/* 23 22 21 20 19 28 17 16 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0 */
+/*  -  -  -  -  -  -  -  - R4 R3 R2 R1 R0 G5 G4 G3 G2 G1 G0 B4 B3 B2 B1 B0 */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_16TO16	DISPLAY_PIXEL_CODING_DPI_RGB(16, 16, 0)
+/*  -  -  -  -  -  - R5 R4 R3 R2 R1 R0 G5 G4 G3 G2 G1 G0 B5 B4 B3 B2 B1 B0 */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_18TO18	DISPLAY_PIXEL_CODING_DPI_RGB(18, 18, 0)
+/*  -  -  - R4 R3 R2 R1 R0  -  - G5 G4 G3 G2 G1 G0  -  -  - B4 B3 B2 B1 B0 */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_16TO20	DISPLAY_PIXEL_CODING_DPI_RGB(16, 20, 0)
+/*  -  - R4 R3 R2 R1 R0  -  -  - G5 G4 G3 G2 G1 G0  -  - B4 B3 B2 B1 B0  - */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_16TO22	DISPLAY_PIXEL_CODING_DPI_RGB(16, 22, 0)
+/*  -  - R5 R4 R3 R2 R1 R0  -  - G5 G4 G3 G2 G1 G0  -  - B5 B4 B3 B2 B1 B0 */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_18TO22	DISPLAY_PIXEL_CODING_DPI_RGB(18, 22, 0)
+/* R7 R6 R5 R4 R3 R2 R1 R0 G7 G6 G5 G4 G3 G2 G1 G0 B7 B6 B5 B4 B3 B2 B1 B0 */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_24TO24	DISPLAY_PIXEL_CODING_DPI_RGB(24, 24, 0)
+
+/* Non-standard DPI pixel codings. */
+/* 23 22 21 20 19 28 17 16 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0 */
+/*  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - R7 R6 R5 R4 R3 R2 R1 R0 */
+/*  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - G7 G6 G5 G4 G3 G2 G1 G0 */
+/*  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - B7 B6 B5 B4 B3 B2 B1 B0 */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_24TO8	DISPLAY_PIXEL_CODING_DPI_RGB(24, 8, 0)
+/*  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - R5 R4 R3 R2 R1 R0 G5 G4 G3 */
+/*  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - G2 G1 G0 B5 B4 B3 B2 B1 B0 */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_18TO9	DISPLAY_PIXEL_CODING_DPI_RGB(18, 9, 0)
+/*  -  -  -  -  -  -  -  -  -  -  -  - R3 R2 R1 R0 G3 G2 G1 G0 B3 B2 B1 B0 */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_12TO12	DISPLAY_PIXEL_CODING_DPI_RGB(12, 12, 0)
+/*  -  -  -  -  -  -  -  -  -  -  -  - R7 R6 R5 R4 R3 R2 R1 R0 G7 G6 G5 G4 */
+/*  -  -  -  -  -  -  -  -  -  -  -  - G3 G2 G1 G0 B7 B6 B5 B4 B3 B2 B1 B0 */
+#define DISPLAY_PIXEL_CODING_DPI_RGB_24TO12	DISPLAY_PIXEL_CODING_DPI_RGB(24, 12, 0)
+
 /* -----------------------------------------------------------------------------
  * Display Entity
  */
-- 
1.8.1.5


^ permalink raw reply related	[flat|nested] 83+ messages in thread

end of thread, other threads:[~2013-10-18 11:55 UTC | newest]

Thread overview: 83+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-08-09 17:14 [PATCH/RFC v3 00/19] Common Display Framework Laurent Pinchart
2013-08-09 17:14 ` [PATCH/RFC v3 01/19] OMAPDSS: panels: Rename Kconfig options to OMAP2_DISPLAY_* Laurent Pinchart
2013-08-09 17:14 ` [PATCH/RFC v3 02/19] video: Add Common Display Framework core Laurent Pinchart
2013-09-02  8:42   ` Tomi Valkeinen
2013-09-03 11:29     ` Laurent Pinchart
2013-08-09 17:14 ` [PATCH/RFC v3 03/19] video: display: Add video and stream control operations Laurent Pinchart
2013-08-09 17:14 ` [PATCH/RFC v3 04/19] video: display: Add display entity notifier Laurent Pinchart
2013-08-09 17:14 ` [PATCH/RFC v3 05/19] video: display: Graph helpers Laurent Pinchart
2013-08-09 17:14 ` [PATCH/RFC v3 06/19] video: display: OF support Laurent Pinchart
2013-08-13 14:37   ` Philipp Zabel
2013-08-21  1:02     ` Laurent Pinchart
2013-08-21  9:10       ` Philipp Zabel
2013-08-22  0:51         ` Laurent Pinchart
2013-08-09 17:14 ` [PATCH/RFC v3 07/19] video: display: Add pixel coding definitions Laurent Pinchart
2013-08-09 17:14 ` [PATCH/RFC v3 08/19] video: display: Add MIPI DBI bus support Laurent Pinchart
2013-08-14  0:52   ` Rob Clark
2013-08-20 13:26     ` Laurent Pinchart
2013-08-26 11:10   ` Tomi Valkeinen
2013-09-06 14:09     ` Laurent Pinchart
2013-09-06 15:43       ` Tomi Valkeinen
2013-09-07  9:35         ` Tomi Valkeinen
2013-09-04 10:50   ` Vikas Sajjan
2013-09-06 14:37     ` Laurent Pinchart
2013-09-18 10:59       ` Vikas Sajjan
2013-09-04 12:52   ` Vikas Sajjan
2013-09-06 14:56     ` Laurent Pinchart
2013-08-09 17:15 ` [PATCH/RFC v3 09/19] video: panel: Add DPI panel support Laurent Pinchart
2013-08-09 17:15 ` [PATCH/RFC v3 10/19] video: panel: Add R61505 " Laurent Pinchart
2013-08-09 17:15 ` [PATCH/RFC v3 11/19] video: panel: Add R61517 " Laurent Pinchart
2013-08-09 17:15 ` [PATCH/RFC v3 12/19] video: display: Add VGA Digital to Analog Converter support Laurent Pinchart
2013-08-09 17:15 ` [PATCH/RFC v3 13/19] video: display: Add VGA connector support Laurent Pinchart
2013-08-09 17:15 ` [PATCH/RFC v3 14/19] ARM: shmobile: r8a7790: Add DU clocks for DT Laurent Pinchart
2013-08-09 17:15 ` [PATCH/RFC v3 15/19] ARM: shmobile: r8a7790: Add DU device node to device tree Laurent Pinchart
2013-08-09 17:15 ` [PATCH/RFC v3 16/19] ARM: shmobile: marzen: Port DU platform data to CDF Laurent Pinchart
2013-08-09 17:15 ` [PATCH/RFC v3 17/19] ARM: shmobile: lager: " Laurent Pinchart
2013-08-09 17:15 ` [PATCH/RFC v3 18/19] ARM: shmobile: lager-reference: Add display device nodes to device tree Laurent Pinchart
2013-08-09 17:15 ` [PATCH/RFC v3 19/19] drm/rcar-du: Port to the Common Display Framework Laurent Pinchart
2013-08-14  0:43 ` [PATCH/RFC v3 00/19] " Rob Clark
2013-08-20 15:24   ` Laurent Pinchart
2013-08-20 18:40     ` Rob Clark
2013-08-21  7:09       ` Sascha Hauer
2013-08-21 12:22         ` Rob Clark
2013-09-06 16:16           ` Laurent Pinchart
2013-09-09 12:12           ` Tomi Valkeinen
2013-09-09 14:17             ` Rob Clark
2013-09-09 14:58               ` Tomi Valkeinen
2013-09-09 15:10                 ` Rob Clark
2013-09-02 11:06 ` Tomi Valkeinen
2013-09-30 13:48 ` Tomi Valkeinen
2013-10-02 12:23   ` Andrzej Hajda
2013-10-02 12:23     ` Andrzej Hajda
2013-10-02 13:24     ` Tomi Valkeinen
2013-10-02 13:24       ` Tomi Valkeinen
2013-10-02 13:24       ` Tomi Valkeinen
2013-10-09 14:08       ` Andrzej Hajda
2013-10-09 14:08         ` Andrzej Hajda
2013-10-11  6:37         ` Tomi Valkeinen
2013-10-11  6:37           ` Tomi Valkeinen
2013-10-11  6:37           ` Tomi Valkeinen
2013-10-11 11:19           ` Andrzej Hajda
2013-10-11 11:19             ` Andrzej Hajda
2013-10-11 12:30             ` Tomi Valkeinen
2013-10-11 12:30               ` Tomi Valkeinen
2013-10-11 12:30               ` Tomi Valkeinen
2013-10-11 14:16               ` Andrzej Hajda
2013-10-11 14:16                 ` Andrzej Hajda
2013-10-11 14:45                 ` Tomi Valkeinen
2013-10-11 14:45                   ` Tomi Valkeinen
2013-10-11 14:45                   ` Tomi Valkeinen
2013-10-17  7:48                   ` Andrzej Hajda
2013-10-17  7:48                     ` Andrzej Hajda
2013-10-17  8:18                     ` Tomi Valkeinen
2013-10-17  8:18                       ` Tomi Valkeinen
2013-10-17  8:18                       ` Tomi Valkeinen
2013-10-17 12:26                       ` Andrzej Hajda
2013-10-17 12:26                         ` Andrzej Hajda
2013-10-17 12:55                         ` Tomi Valkeinen
2013-10-17 12:55                           ` Tomi Valkeinen
2013-10-17 12:55                           ` Tomi Valkeinen
2013-10-18 11:55                           ` Andrzej Hajda
2013-10-18 11:55                             ` Andrzej Hajda
2013-08-09 23:02 Laurent Pinchart
2013-08-09 23:03 ` [PATCH/RFC v3 07/19] video: display: Add pixel coding definitions Laurent Pinchart
2013-08-09 23:03   ` Laurent Pinchart

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.