Commit 8337486a authored by Dave Airlie's avatar Dave Airlie

Merge branch 'drm/next/du' of git://linuxtv.org/pinchartl/fbdev into drm-next

Commit "drm/rcar-du: Use struct videomode in platform data" touches board code
in arch/arm/mach-shmobile. There is, to the best of my knowledge, no risk of
conflict for v3.18. Simon, are you fine with getting those changes merged
through Dave's tree (and could you confirm that no conflict should occur) ?

Simon acked the merge:
Acked-by: default avatarSimon Horman <horms+renesas@verge.net.au>

* 'drm/next/du' of git://linuxtv.org/pinchartl/fbdev:
  drm/rcar-du: Add OF support
  drm/rcar-du: Use struct videomode in platform data
  video: Add DT bindings for the R-Car Display Unit
  video: Add THC63LVDM83D DT bindings documentation
  video: Add ADV7123 DT bindings documentation
  video: Add DT binding documentation for VGA connector
  devicetree: Add vendor prefix "thine" to vendor-prefixes.txt
  devicetree: Add vendor prefix "mitsubishi" to vendor-prefixes.txt
  drm/shmob: Update copyright notice
  drm/rcar-du: Update copyright notice
parents 109ab909 96c02691
......@@ -83,6 +83,7 @@ maxim Maxim Integrated Products
mediatek MediaTek Inc.
micrel Micrel Inc.
microchip Microchip Technology Inc.
mitsubishi Mitsubishi Electric Corporation
mosaixtech Mosaix Technologies, Inc.
moxa Moxa
mpl MPL AG
......@@ -133,6 +134,7 @@ st STMicroelectronics
ste ST-Ericsson
stericsson ST-Ericsson
synology Synology, Inc.
thine THine Electronics, Inc.
ti Texas Instruments
tlm Trusted Logic Mobility
toradex Toradex AG
......
Analog Device ADV7123 Video DAC
-------------------------------
The ADV7123 is a digital-to-analog converter that outputs VGA signals from a
parallel video input.
Required properties:
- compatible: Should be "adi,adv7123"
Optional properties:
- psave-gpios: Power save control GPIO
Required nodes:
The ADV7123 has two video ports. Their connections are modeled using the OF
graph bindings specified in Documentation/devicetree/bindings/graph.txt.
- Video port 0 for DPI input
- Video port 1 for VGA output
Example
-------
adv7123: encoder@0 {
compatible = "adi,adv7123";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
adv7123_in: endpoint@0 {
remote-endpoint = <&dpi_out>;
};
};
port@1 {
reg = <1>;
adv7123_out: endpoint@0 {
remote-endpoint = <&vga_connector_in>;
};
};
};
};
* Renesas R-Car Display Unit (DU)
Required Properties:
- compatible: must be one of the following.
- "renesas,du-r8a7779" for R8A7779 (R-Car H1) compatible DU
- "renesas,du-r8a7790" for R8A7790 (R-Car H2) compatible DU
- "renesas,du-r8a7791" for R8A7791 (R-Car M2) compatible DU
- reg: A list of base address and length of each memory resource, one for
each entry in the reg-names property.
- reg-names: Name of the memory resources. The DU requires one memory
resource for the DU core (named "du") and one memory resource for each
LVDS encoder (named "lvds.x" with "x" being the LVDS controller numerical
index).
- interrupt-parent: phandle of the parent interrupt controller.
- interrupts: Interrupt specifiers for the DU interrupts.
- clocks: A list of phandles + clock-specifier pairs, one for each entry in
the clock-names property.
- clock-names: Name of the clocks. This property is model-dependent.
- R8A7779 uses a single functional clock. The clock doesn't need to be
named.
- R8A7790 and R8A7791 use one functional clock per channel and one clock
per LVDS encoder. The functional clocks must be named "du.x" with "x"
being the channel numerical index. The LVDS clocks must be named
"lvds.x" with "x" being the LVDS encoder numerical index.
Required nodes:
The connections to the DU output video ports are modeled using the OF graph
bindings specified in Documentation/devicetree/bindings/graph.txt.
The following table lists for each supported model the port number
corresponding to each DU output.
Port 0 Port1 Port2
-----------------------------------------------------------------------------
R8A7779 (H1) DPAD 0 DPAD 1 -
R8A7790 (H2) DPAD LVDS 0 LVDS 1
R8A7791 (M2) DPAD LVDS 0 -
Example: R8A7790 (R-Car H2) DU
du: du@feb00000 {
compatible = "renesas,du-r8a7790";
reg = <0 0xfeb00000 0 0x70000>,
<0 0xfeb90000 0 0x1c>,
<0 0xfeb94000 0 0x1c>;
reg-names = "du", "lvds.0", "lvds.1";
interrupt-parent = <&gic>;
interrupts = <0 256 IRQ_TYPE_LEVEL_HIGH>,
<0 268 IRQ_TYPE_LEVEL_HIGH>,
<0 269 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp7_clks R8A7790_CLK_DU0>,
<&mstp7_clks R8A7790_CLK_DU1>,
<&mstp7_clks R8A7790_CLK_DU2>,
<&mstp7_clks R8A7790_CLK_LVDS0>,
<&mstp7_clks R8A7790_CLK_LVDS1>;
clock-names = "du.0", "du.1", "du.2", "lvds.0", "lvds.1";
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 {
};
};
};
};
THine Electronics THC63LVDM83D LVDS serializer
----------------------------------------------
The THC63LVDM83D is an LVDS serializer designed to support pixel data
transmission between a host and a flat panel.
Required properties:
- compatible: Should be "thine,thc63lvdm83d"
Optional properties:
- pwdn-gpios: Power down control GPIO
Required nodes:
The THC63LVDM83D has two video ports. Their connections are modeled using the
OFgraph bindings specified in Documentation/devicetree/bindings/graph.txt.
- Video port 0 for CMOS/TTL input
- Video port 1 for LVDS output
Example
-------
lvds_enc: encoder@0 {
compatible = "thine,thc63lvdm83d";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
lvds_enc_in: endpoint@0 {
remote-endpoint = <&rgb_out>;
};
};
port@1 {
reg = <1>;
lvds_enc_out: endpoint@0 {
remote-endpoint = <&panel_in>;
};
};
};
};
VGA Connector
=============
Required properties:
- compatible: "vga-connector"
Optional properties:
- label: a symbolic name for the connector corresponding to a hardware label
- ddc-i2c-bus: phandle to the I2C bus that is connected to VGA DDC
Required nodes:
The VGA connector internal connections are modeled using the OF graph bindings
specified in Documentation/devicetree/bindings/graph.txt.
The VGA connector has a single port that must be connected to a video source
port.
Example
-------
vga0: connector@0 {
compatible = "vga-connector";
label = "vga";
ddc-i2c-bus = <&i2c3>;
port {
vga_connector_in: endpoint {
remote-endpoint = <&adv7123_out>;
};
};
};
......@@ -41,16 +41,15 @@ static struct rcar_du_encoder_data koelsch_du_encoders[] = {
.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,
.pixelclock = 65000000,
.hactive = 1024,
.hfront_porch = 20,
.hback_porch = 160,
.hsync_len = 136,
.vactive = 768,
.vfront_porch = 3,
.vback_porch = 29,
.vsync_len = 6,
},
},
},
......
......@@ -63,16 +63,15 @@ static struct rcar_du_encoder_data koelsch_du_encoders[] = {
.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,
.pixelclock = 65000000,
.hactive = 1024,
.hfront_porch = 20,
.hback_porch = 160,
.hsync_len = 136,
.vactive = 768,
.vfront_porch = 3,
.vback_porch = 29,
.vsync_len = 6,
},
},
},
......
......@@ -43,16 +43,15 @@ static struct rcar_du_encoder_data lager_du_encoders[] = {
.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,
.pixelclock = 65000000,
.hactive = 1024,
.hfront_porch = 20,
.hback_porch = 160,
.hsync_len = 136,
.vactive = 768,
.vfront_porch = 3,
.vback_porch = 29,
.vsync_len = 6,
},
},
},
......
......@@ -99,16 +99,15 @@ static struct rcar_du_encoder_data lager_du_encoders[] = {
.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,
.pixelclock = 65000000,
.hactive = 1024,
.hfront_porch = 20,
.hback_porch = 160,
.hsync_len = 136,
.vactive = 768,
.vfront_porch = 3,
.vback_porch = 29,
.vsync_len = 6,
},
},
},
......
......@@ -192,16 +192,15 @@ static struct rcar_du_encoder_data du_encoders[] = {
.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,
.pixelclock = 65000000,
.hactive = 1024,
.hfront_porch = 20,
.hback_porch = 160,
.hsync_len = 136,
.vactive = 768,
.vfront_porch = 3,
.vback_porch = 29,
.vsync_len = 6,
},
},
},
......
......@@ -6,6 +6,7 @@ config DRM_RCAR_DU
select DRM_KMS_CMA_HELPER
select DRM_GEM_CMA_HELPER
select DRM_KMS_FB_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.
......
/*
* rcar_du_crtc.c -- R-Car Display Unit CRTCs
*
* Copyright (C) 2013 Renesas Corporation
* Copyright (C) 2013-2014 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......
/*
* rcar_du_crtc.h -- R-Car Display Unit CRTCs
*
* Copyright (C) 2013 Renesas Corporation
* Copyright (C) 2013-2014 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......
/*
* rcar_du_drv.c -- R-Car Display Unit DRM driver
*
* Copyright (C) 2013 Renesas Corporation
* Copyright (C) 2013-2014 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......@@ -15,6 +15,7 @@
#include <linux/io.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/slab.h>
......@@ -29,6 +30,97 @@
#include "rcar_du_kms.h"
#include "rcar_du_regs.h"
/* -----------------------------------------------------------------------------
* Device Information
*/
static const struct rcar_du_device_info rcar_du_r8a7779_info = {
.features = 0,
.num_crtcs = 2,
.routes = {
/* R8A7779 has two RGB outputs and one (currently unsupported)
* TCON output.
*/
[RCAR_DU_OUTPUT_DPAD0] = {
.possible_crtcs = BIT(0),
.encoder_type = DRM_MODE_ENCODER_NONE,
.port = 0,
},
[RCAR_DU_OUTPUT_DPAD1] = {
.possible_crtcs = BIT(1) | BIT(0),
.encoder_type = DRM_MODE_ENCODER_NONE,
.port = 1,
},
},
.num_lvds = 0,
};
static const struct rcar_du_device_info rcar_du_r8a7790_info = {
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_DEFR8,
.quirks = RCAR_DU_QUIRK_ALIGN_128B | RCAR_DU_QUIRK_LVDS_LANES,
.num_crtcs = 3,
.routes = {
/* R8A7790 has one RGB output, two LVDS outputs and one
* (currently unsupported) TCON output.
*/
[RCAR_DU_OUTPUT_DPAD0] = {
.possible_crtcs = BIT(2) | BIT(1) | BIT(0),
.encoder_type = DRM_MODE_ENCODER_NONE,
.port = 0,
},
[RCAR_DU_OUTPUT_LVDS0] = {
.possible_crtcs = BIT(0),
.encoder_type = DRM_MODE_ENCODER_LVDS,
.port = 1,
},
[RCAR_DU_OUTPUT_LVDS1] = {
.possible_crtcs = BIT(2) | BIT(1),
.encoder_type = DRM_MODE_ENCODER_LVDS,
.port = 2,
},
},
.num_lvds = 2,
};
static const struct rcar_du_device_info rcar_du_r8a7791_info = {
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_DEFR8,
.num_crtcs = 2,
.routes = {
/* R8A7791 has one RGB output, one LVDS output and one
* (currently unsupported) TCON output.
*/
[RCAR_DU_OUTPUT_DPAD0] = {
.possible_crtcs = BIT(1),
.encoder_type = DRM_MODE_ENCODER_NONE,
.port = 0,
},
[RCAR_DU_OUTPUT_LVDS0] = {
.possible_crtcs = BIT(0),
.encoder_type = DRM_MODE_ENCODER_LVDS,
.port = 1,
},
},
.num_lvds = 1,
};
static const struct platform_device_id rcar_du_id_table[] = {
{ "rcar-du-r8a7779", (kernel_ulong_t)&rcar_du_r8a7779_info },
{ "rcar-du-r8a7790", (kernel_ulong_t)&rcar_du_r8a7790_info },
{ "rcar-du-r8a7791", (kernel_ulong_t)&rcar_du_r8a7791_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 },
{ .compatible = "renesas,du-r8a7791", .data = &rcar_du_r8a7791_info },
{ }
};
MODULE_DEVICE_TABLE(of, rcar_du_of_table);
/* -----------------------------------------------------------------------------
* DRM operations
*/
......@@ -53,12 +145,13 @@ 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 device_node *np = pdev->dev.of_node;
struct rcar_du_platform_data *pdata = pdev->dev.platform_data;
struct rcar_du_device *rcdu;
struct resource *mem;
int ret;
if (pdata == NULL) {
if (pdata == NULL && np == NULL) {
dev_err(dev->dev, "no platform data\n");
return -ENODEV;
}
......@@ -71,7 +164,8 @@ static int rcar_du_load(struct drm_device *dev, unsigned long flags)
rcdu->dev = &pdev->dev;
rcdu->pdata = pdata;
rcdu->info = (struct rcar_du_device_info *)pdev->id_entry->driver_data;
rcdu->info = np ? of_match_device(rcar_du_of_table, rcdu->dev)->data
: (void *)platform_get_device_id(pdev)->driver_data;
rcdu->ddev = dev;
dev->dev_private = rcdu;
......@@ -232,77 +326,6 @@ static int rcar_du_remove(struct platform_device *pdev)
return 0;
}
static const struct rcar_du_device_info rcar_du_r8a7779_info = {
.features = 0,
.num_crtcs = 2,
.routes = {
/* R8A7779 has two RGB outputs and one (currently unsupported)
* TCON output.
*/
[RCAR_DU_OUTPUT_DPAD0] = {
.possible_crtcs = BIT(0),
.encoder_type = DRM_MODE_ENCODER_NONE,
},
[RCAR_DU_OUTPUT_DPAD1] = {
.possible_crtcs = BIT(1) | BIT(0),
.encoder_type = DRM_MODE_ENCODER_NONE,
},
},
.num_lvds = 0,
};
static const struct rcar_du_device_info rcar_du_r8a7790_info = {
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_DEFR8,
.quirks = RCAR_DU_QUIRK_ALIGN_128B | RCAR_DU_QUIRK_LVDS_LANES,
.num_crtcs = 3,
.routes = {
/* R8A7790 has one RGB output, two LVDS outputs and one
* (currently unsupported) TCON output.
*/
[RCAR_DU_OUTPUT_DPAD0] = {
.possible_crtcs = BIT(2) | BIT(1) | BIT(0),
.encoder_type = DRM_MODE_ENCODER_NONE,
},
[RCAR_DU_OUTPUT_LVDS0] = {
.possible_crtcs = BIT(0),
.encoder_type = DRM_MODE_ENCODER_LVDS,
},
[RCAR_DU_OUTPUT_LVDS1] = {
.possible_crtcs = BIT(2) | BIT(1),
.encoder_type = DRM_MODE_ENCODER_LVDS,
},
},
.num_lvds = 2,
};
static const struct rcar_du_device_info rcar_du_r8a7791_info = {
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK | RCAR_DU_FEATURE_DEFR8,
.num_crtcs = 2,
.routes = {
/* R8A7791 has one RGB output, one LVDS output and one
* (currently unsupported) TCON output.
*/
[RCAR_DU_OUTPUT_DPAD0] = {
.possible_crtcs = BIT(1),
.encoder_type = DRM_MODE_ENCODER_NONE,
},
[RCAR_DU_OUTPUT_LVDS0] = {
.possible_crtcs = BIT(0),
.encoder_type = DRM_MODE_ENCODER_LVDS,
},
},
.num_lvds = 1,
};
static const struct platform_device_id rcar_du_id_table[] = {
{ "rcar-du-r8a7779", (kernel_ulong_t)&rcar_du_r8a7779_info },
{ "rcar-du-r8a7790", (kernel_ulong_t)&rcar_du_r8a7790_info },
{ "rcar-du-r8a7791", (kernel_ulong_t)&rcar_du_r8a7791_info },
{ }
};
MODULE_DEVICE_TABLE(platform, rcar_du_id_table);
static struct platform_driver rcar_du_platform_driver = {
.probe = rcar_du_probe,
.remove = rcar_du_remove,
......@@ -310,6 +333,7 @@ static struct platform_driver rcar_du_platform_driver = {
.owner = THIS_MODULE,
.name = "rcar-du",
.pm = &rcar_du_pm_ops,
.of_match_table = rcar_du_of_table,
},
.id_table = rcar_du_id_table,
};
......
/*
* rcar_du_drv.h -- R-Car Display Unit DRM driver
*
* Copyright (C) 2013 Renesas Corporation
* Copyright (C) 2013-2014 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......@@ -37,6 +37,7 @@ struct rcar_du_lvdsenc;
* struct rcar_du_output_routing - Output routing specification
* @possible_crtcs: bitmask of possible CRTCs for the output
* @encoder_type: DRM type of the internal encoder associated with the output
* @port: device tree port number corresponding to this output route
*
* 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
......@@ -45,6 +46,7 @@ struct rcar_du_lvdsenc;
struct rcar_du_output_routing {
unsigned int possible_crtcs;
unsigned int encoder_type;
unsigned int port;
};
/*
......
/*
* rcar_du_encoder.c -- R-Car Display Unit Encoder
*
* Copyright (C) 2013 Renesas Corporation
* Copyright (C) 2013-2014 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......@@ -142,7 +142,8 @@ static const struct drm_encoder_funcs encoder_funcs = {
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)
const struct rcar_du_encoder_data *data,
struct device_node *np)
{
struct rcar_du_encoder *renc;
unsigned int encoder_type;
......@@ -189,9 +190,11 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
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_LVDS: {
const struct rcar_du_panel_data *pdata =
data ? &data->connector.lvds.panel : NULL;
return rcar_du_lvds_connector_init(rcdu, renc, pdata, np);
}
case DRM_MODE_ENCODER_DAC:
return rcar_du_vga_connector_init(rcdu, renc);
......
/*
* rcar_du_encoder.h -- R-Car Display Unit Encoder
*
* Copyright (C) 2013 Renesas Corporation
* Copyright (C) 2013-2014 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......@@ -44,6 +44,7 @@ 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);
const struct rcar_du_encoder_data *data,
struct device_node *np);
#endif /* __RCAR_DU_ENCODER_H__ */
/*
* rcar_du_group.c -- R-Car Display Unit Channels Pair
*
* Copyright (C) 2013 Renesas Corporation
* Copyright (C) 2013-2014 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......
/*
* rcar_du_group.c -- R-Car Display Unit Planes and CRTCs Group
*
* Copyright (C) 2013 Renesas Corporation
* Copyright (C) 2013-2014 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......
/*
* rcar_du_kms.c -- R-Car Display Unit Mode Setting
*
* Copyright (C) 2013 Renesas Corporation
* Copyright (C) 2013-2014 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......@@ -17,6 +17,8 @@
#include <drm/drm_fb_cma_helper.h>
#include <drm/drm_gem_cma_helper.h>
#include <linux/of_graph.h>
#include "rcar_du_crtc.h"
#include "rcar_du_drv.h"
#include "rcar_du_encoder.h"
......@@ -188,6 +190,205 @@ static const struct drm_mode_config_funcs rcar_du_mode_config_funcs = {
.output_poll_changed = rcar_du_output_poll_changed,
};
static int rcar_du_encoders_init_pdata(struct rcar_du_device *rcdu)
{
unsigned int num_encoders = 0;
unsigned int i;
int 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];
if (pdata->type == RCAR_DU_ENCODER_UNUSED)
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_encoder_init(rcdu, pdata->type, pdata->output,
pdata, NULL);
if (ret < 0)
return ret;
num_encoders++;
}
return num_encoders;
}
static int rcar_du_encoders_init_dt_one(struct rcar_du_device *rcdu,
enum rcar_du_output output,
struct of_endpoint *ep)
{
static const struct {
const char *compatible;
enum rcar_du_encoder_type type;
} encoders[] = {
{ "adi,adv7123", RCAR_DU_ENCODER_VGA },
{ "thine,thc63lvdm83d", RCAR_DU_ENCODER_LVDS },
};
enum rcar_du_encoder_type enc_type = RCAR_DU_ENCODER_NONE;
struct device_node *connector = NULL;
struct device_node *encoder = NULL;
struct device_node *prev = NULL;
struct device_node *entity_ep_node;
struct device_node *entity;
int ret;
/*
* Locate the connected entity and infer its type from the number of
* endpoints.
*/
entity = of_graph_get_remote_port_parent(ep->local_node);
if (!entity) {
dev_dbg(rcdu->dev, "unconnected endpoint %s, skipping\n",
ep->local_node->full_name);
return 0;
}
entity_ep_node = of_parse_phandle(ep->local_node, "remote-endpoint", 0);
while (1) {
struct device_node *ep_node;
ep_node = of_graph_get_next_endpoint(entity, prev);
of_node_put(prev);
prev = ep_node;
if (!ep_node)
break;
if (ep_node == entity_ep_node)
continue;
/*
* We've found one endpoint other than the input, this must
* be an encoder. Locate the connector.
*/
encoder = entity;
connector = of_graph_get_remote_port_parent(ep_node);
of_node_put(ep_node);
if (!connector) {
dev_warn(rcdu->dev,
"no connector for encoder %s, skipping\n",
encoder->full_name);
of_node_put(entity_ep_node);
of_node_put(encoder);
return 0;
}
break;
}
of_node_put(entity_ep_node);
if (encoder) {
/*
* If an encoder has been found, get its type based on its
* compatible string.
*/
unsigned int i;
for (i = 0; i < ARRAY_SIZE(encoders); ++i) {
if (of_device_is_compatible(encoder,
encoders[i].compatible)) {
enc_type = encoders[i].type;
break;
}
}
if (i == ARRAY_SIZE(encoders)) {
dev_warn(rcdu->dev,
"unknown encoder type for %s, skipping\n",
encoder->full_name);
of_node_put(encoder);
of_node_put(connector);
return 0;
}
} else {
/*
* If no encoder has been found the entity must be the
* connector.
*/
connector = entity;
}
ret = rcar_du_encoder_init(rcdu, enc_type, output, NULL, connector);
of_node_put(encoder);
of_node_put(connector);
return ret < 0 ? ret : 1;
}
static int rcar_du_encoders_init_dt(struct rcar_du_device *rcdu)
{
struct device_node *np = rcdu->dev->of_node;
struct device_node *prev = NULL;
unsigned int num_encoders = 0;
/*
* Iterate over the endpoints and create one encoder for each output
* pipeline.
*/
while (1) {
struct device_node *ep_node;
enum rcar_du_output output;
struct of_endpoint ep;
unsigned int i;
int ret;
ep_node = of_graph_get_next_endpoint(np, prev);
of_node_put(prev);
prev = ep_node;
if (ep_node == NULL)
break;
ret = of_graph_parse_endpoint(ep_node, &ep);
if (ret < 0) {
of_node_put(ep_node);
return ret;
}
/* Find the output route corresponding to the port number. */
for (i = 0; i < RCAR_DU_OUTPUT_MAX; ++i) {
if (rcdu->info->routes[i].possible_crtcs &&
rcdu->info->routes[i].port == ep.port) {
output = i;
break;
}
}
if (i == RCAR_DU_OUTPUT_MAX) {
dev_warn(rcdu->dev,
"port %u references unexisting output, skipping\n",
ep.port);
continue;
}
/* Process the output pipeline. */
ret = rcar_du_encoders_init_dt_one(rcdu, output, &ep);
if (ret < 0) {
of_node_put(ep_node);
return ret;
}
num_encoders += ret;
}
return num_encoders;
}
int rcar_du_modeset_init(struct rcar_du_device *rcdu)
{
static const unsigned int mmio_offsets[] = {
......@@ -197,6 +398,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;
unsigned int num_groups;
unsigned int i;
int ret;
......@@ -240,28 +442,15 @@ int rcar_du_modeset_init(struct rcar_du_device *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];
if (pdata->type == RCAR_DU_ENCODER_UNUSED)
continue;
if (rcdu->pdata)
ret = rcar_du_encoders_init_pdata(rcdu);
else
ret = rcar_du_encoders_init_dt(rcdu);
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;
}
if (ret < 0)
return ret;
ret = rcar_du_encoder_init(rcdu, pdata->type, pdata->output,
pdata);
if (ret < 0)
return ret;
}
num_encoders = ret;
/* Set the possible CRTCs and possible clones. There's always at least
* one way for all encoders to clone each other, set all bits in the
......@@ -273,7 +462,7 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
&rcdu->info->routes[renc->output];
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. */
......
/*
* rcar_du_kms.h -- R-Car Display Unit Mode Setting
*
* Copyright (C) 2013 Renesas Corporation
* Copyright (C) 2013-2014 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......
/*
* rcar_du_lvdscon.c -- R-Car Display Unit LVDS Connector
*
* Copyright (C) 2013 Renesas Corporation
* Copyright (C) 2013-2014 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......@@ -15,6 +15,10 @@
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
#include <video/display_timing.h>
#include <video/of_display_timing.h>
#include <video/videomode.h>
#include "rcar_du_drv.h"
#include "rcar_du_encoder.h"
#include "rcar_du_kms.h"
......@@ -23,7 +27,7 @@
struct rcar_du_lvds_connector {
struct rcar_du_connector connector;
const struct rcar_du_panel_data *panel;
struct rcar_du_panel_data panel;
};
#define to_rcar_lvds_connector(c) \
......@@ -40,18 +44,9 @@ static int rcar_du_lvds_connector_get_modes(struct drm_connector *connector)
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_display_mode_from_videomode(&lvdscon->panel.mode, mode);
drm_mode_probed_add(connector, mode);
return 1;
......@@ -83,7 +78,8 @@ static const struct drm_connector_funcs connector_funcs = {
int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
struct rcar_du_encoder *renc,
const struct rcar_du_panel_data *panel)
const struct rcar_du_panel_data *panel,
/* TODO const */ struct device_node *np)
{
struct rcar_du_lvds_connector *lvdscon;
struct drm_connector *connector;
......@@ -93,11 +89,24 @@ int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
if (lvdscon == NULL)
return -ENOMEM;
lvdscon->panel = panel;
if (panel) {
lvdscon->panel = *panel;
} else {
struct display_timing timing;
ret = of_get_display_timing(np, "panel-timing", &timing);
if (ret < 0)
return ret;
videomode_from_timing(&timing, &lvdscon->panel.mode);
of_property_read_u32(np, "width-mm", &lvdscon->panel.width_mm);
of_property_read_u32(np, "height-mm", &lvdscon->panel.height_mm);
}
connector = &lvdscon->connector.connector;
connector->display_info.width_mm = panel->width_mm;
connector->display_info.height_mm = panel->height_mm;
connector->display_info.width_mm = lvdscon->panel.width_mm;
connector->display_info.height_mm = lvdscon->panel.height_mm;
ret = drm_connector_init(rcdu->ddev, connector, &connector_funcs,
DRM_MODE_CONNECTOR_LVDS);
......
/*
* rcar_du_lvdscon.h -- R-Car Display Unit LVDS Connector
*
* Copyright (C) 2013 Renesas Corporation
* Copyright (C) 2013-2014 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......@@ -20,6 +20,7 @@ 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);
const struct rcar_du_panel_data *panel,
struct device_node *np);
#endif /* __RCAR_DU_LVDSCON_H__ */
/*
* rcar_du_lvdsenc.c -- R-Car Display Unit LVDS Encoder
*
* Copyright (C) 2013 Renesas Corporation
* Copyright (C) 2013-2014 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......
/*
* rcar_du_lvdsenc.h -- R-Car Display Unit LVDS Encoder
*
* Copyright (C) 2013 Renesas Corporation
* Copyright (C) 2013-2014 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......
/*
* rcar_du_plane.c -- R-Car Display Unit Planes
*
* Copyright (C) 2013 Renesas Corporation
* Copyright (C) 2013-2014 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......
/*
* rcar_du_plane.h -- R-Car Display Unit Planes
*
* Copyright (C) 2013 Renesas Corporation
* Copyright (C) 2013-2014 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......
/*
* rcar_du_vgacon.c -- R-Car Display Unit VGA Connector
*
* Copyright (C) 2013 Renesas Corporation
* Copyright (C) 2013-2014 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......
/*
* rcar_du_vgacon.h -- R-Car Display Unit VGA Connector
*
* Copyright (C) 2013 Renesas Corporation
* Copyright (C) 2013-2014 Renesas Electronics Corporation
*
* Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......
/*
* shmob_drm_backlight.c -- SH Mobile DRM Backlight
*
* Copyright (C) 2012 Renesas Corporation
* Copyright (C) 2012 Renesas Electronics Corporation
*
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......
/*
* shmob_drm_backlight.h -- SH Mobile DRM Backlight
*
* Copyright (C) 2012 Renesas Corporation
* Copyright (C) 2012 Renesas Electronics Corporation
*
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......
/*
* shmob_drm_crtc.c -- SH Mobile DRM CRTCs
*
* Copyright (C) 2012 Renesas Corporation
* Copyright (C) 2012 Renesas Electronics Corporation
*
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......
/*
* shmob_drm_crtc.h -- SH Mobile DRM CRTCs
*
* Copyright (C) 2012 Renesas Corporation
* Copyright (C) 2012 Renesas Electronics Corporation
*
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......
/*
* shmob_drm_drv.c -- SH Mobile DRM driver
*
* Copyright (C) 2012 Renesas Corporation
* Copyright (C) 2012 Renesas Electronics Corporation
*
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......
/*
* shmob_drm.h -- SH Mobile DRM driver
*
* Copyright (C) 2012 Renesas Corporation
* Copyright (C) 2012 Renesas Electronics Corporation
*
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......
/*
* shmob_drm_kms.c -- SH Mobile DRM Mode Setting
*
* Copyright (C) 2012 Renesas Corporation
* Copyright (C) 2012 Renesas Electronics Corporation
*
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......
/*
* shmob_drm_kms.h -- SH Mobile DRM Mode Setting
*
* Copyright (C) 2012 Renesas Corporation
* Copyright (C) 2012 Renesas Electronics Corporation
*
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......
/*
* shmob_drm_plane.c -- SH Mobile DRM Planes
*
* Copyright (C) 2012 Renesas Corporation
* Copyright (C) 2012 Renesas Electronics Corporation
*
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......
/*
* shmob_drm_plane.h -- SH Mobile DRM Planes
*
* Copyright (C) 2012 Renesas Corporation
* Copyright (C) 2012 Renesas Electronics Corporation
*
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......
/*
* shmob_drm_regs.h -- SH Mobile DRM registers
*
* Copyright (C) 2012 Renesas Corporation
* Copyright (C) 2012 Renesas Electronics Corporation
*
* Laurent Pinchart (laurent.pinchart@ideasonboard.com)
*
......
......@@ -14,7 +14,7 @@
#ifndef __RCAR_DU_H__
#define __RCAR_DU_H__
#include <drm/drm_mode.h>
#include <video/videomode.h>
enum rcar_du_output {
RCAR_DU_OUTPUT_DPAD0,
......@@ -35,7 +35,7 @@ enum rcar_du_encoder_type {
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 videomode mode;
};
struct rcar_du_connector_lvds_data {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment