Skip to content

Commit

Permalink
Merge branch 'drm/next/du' of git://linuxtv.org/pinchartl/media into …
Browse files Browse the repository at this point in the history
…drm-next

rcar-du -next branch.

* 'drm/next/du' of git://linuxtv.org/pinchartl/media:
  drm: rcar-du: Fix LVDS start sequence on Gen3
  drm: rcar-du: Fix H/V sync signal polarity configuration
  drm: rcar-du: Fix display timing controller parameter
  drm: rcar-du: Fix dot clock routing configuration
  drm: rcar-du: Add R8A7796 support
  drm: rcar-du: Add R8A7792 support
  drm: rcar-du: Simplify and fix probe error handling
  drm: rcar-du: Fix crash in encoder failure error path
  drm: rcar-du: Remove memory allocation error message
  drm: rcar-du: Remove test for impossible error condition
  drm: rcar-du: Bring HDMI encoder comments in line with the driver
  drm: rcar-du: Constify node argument to rcar_du_lvds_connector_init()
  video: of: Constify node argument to display timing functions
  • Loading branch information
airlied committed Nov 15, 2016
2 parents d8c1abd + 85e8f8d commit 1a3865d
Show file tree
Hide file tree
Showing 11 changed files with 117 additions and 71 deletions.
12 changes: 8 additions & 4 deletions Documentation/devicetree/bindings/display/renesas,du.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ Required Properties:
- "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-W) compatible DU
- "renesas,du-r8a7792" for R8A7792 (R-Car V2H) compatible DU
- "renesas,du-r8a7793" for R8A7793 (R-Car M2-N) compatible DU
- "renesas,du-r8a7794" for R8A7794 (R-Car E2) compatible DU
- "renesas,du-r8a7795" for R8A7795 (R-Car H3) compatible DU
- "renesas,du-r8a7796" for R8A7796 (R-Car M3-W) compatible DU

- reg: A list of base address and length of each memory resource, one for
each entry in the reg-names property.
Expand All @@ -25,10 +27,10 @@ Required Properties:
- 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.
- R8A779[01345] use one functional clock per channel and one clock per LVDS
encoder (if available). 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.
- R8A779[0123456] use one functional clock per channel and one clock per
LVDS encoder (if available). 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.
- In addition to the functional and encoder clocks, all DU versions also
support externally supplied pixel clocks. Those clocks are optional.
When supplied they must be named "dclkin.x" with "x" being the input
Expand All @@ -47,9 +49,11 @@ corresponding to each DU output.
R8A7779 (H1) DPAD 0 DPAD 1 - -
R8A7790 (H2) DPAD LVDS 0 LVDS 1 -
R8A7791 (M2-W) DPAD LVDS 0 - -
R8A7792 (V2H) DPAD 0 DPAD 1 - -
R8A7793 (M2-N) DPAD LVDS 0 - -
R8A7794 (E2) DPAD 0 DPAD 1 - -
R8A7795 (H3) DPAD HDMI 0 HDMI 1 LVDS
R8A7796 (M3-W) DPAD HDMI LVDS -


Example: R8A7790 (R-Car H2) DU
Expand Down
6 changes: 3 additions & 3 deletions drivers/gpu/drm/rcar-du/rcar_du_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,8 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? OTAR2 : OTAR, 0);

/* Signal polarities */
value = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? 0 : DSMR_VSL)
| ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? 0 : DSMR_HSL)
value = ((mode->flags & DRM_MODE_FLAG_PVSYNC) ? DSMR_VSL : 0)
| ((mode->flags & DRM_MODE_FLAG_PHSYNC) ? DSMR_HSL : 0)
| DSMR_DIPM_DISP | DSMR_CSPM;
rcar_du_crtc_write(rcrtc, DSMR, value);

Expand All @@ -172,7 +172,7 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
mode->crtc_vsync_start - 1);
rcar_du_crtc_write(rcrtc, VCR, mode->crtc_vtotal - 1);

rcar_du_crtc_write(rcrtc, DESR, mode->htotal - mode->hsync_start);
rcar_du_crtc_write(rcrtc, DESR, mode->htotal - mode->hsync_start - 1);
rcar_du_crtc_write(rcrtc, DEWR, mode->hdisplay);
}

Expand Down
83 changes: 57 additions & 26 deletions drivers/gpu/drm/rcar-du/rcar_du_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,27 @@ static const struct rcar_du_device_info rcar_du_r8a7791_info = {
.num_lvds = 1,
};

static const struct rcar_du_device_info rcar_du_r8a7792_info = {
.gen = 2,
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
| RCAR_DU_FEATURE_EXT_CTRL_REGS,
.num_crtcs = 2,
.routes = {
/* R8A7792 has two RGB outputs. */
[RCAR_DU_OUTPUT_DPAD0] = {
.possible_crtcs = BIT(0),
.encoder_type = DRM_MODE_ENCODER_NONE,
.port = 0,
},
[RCAR_DU_OUTPUT_DPAD1] = {
.possible_crtcs = BIT(1),
.encoder_type = DRM_MODE_ENCODER_NONE,
.port = 1,
},
},
.num_lvds = 0,
};

static const struct rcar_du_device_info rcar_du_r8a7794_info = {
.gen = 2,
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
Expand Down Expand Up @@ -157,13 +178,39 @@ static const struct rcar_du_device_info rcar_du_r8a7795_info = {
.num_lvds = 1,
};

static const struct rcar_du_device_info rcar_du_r8a7796_info = {
.gen = 3,
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
| RCAR_DU_FEATURE_EXT_CTRL_REGS
| RCAR_DU_FEATURE_VSP1_SOURCE,
.num_crtcs = 3,
.routes = {
/* R8A7796 has one RGB output, one LVDS output and one
* (currently unsupported) HDMI output.
*/
[RCAR_DU_OUTPUT_DPAD0] = {
.possible_crtcs = BIT(2),
.encoder_type = DRM_MODE_ENCODER_NONE,
.port = 0,
},
[RCAR_DU_OUTPUT_LVDS0] = {
.possible_crtcs = BIT(0),
.encoder_type = DRM_MODE_ENCODER_LVDS,
.port = 2,
},
},
.num_lvds = 1,
};

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 },
{ .compatible = "renesas,du-r8a7792", .data = &rcar_du_r8a7792_info },
{ .compatible = "renesas,du-r8a7793", .data = &rcar_du_r8a7791_info },
{ .compatible = "renesas,du-r8a7794", .data = &rcar_du_r8a7794_info },
{ .compatible = "renesas,du-r8a7795", .data = &rcar_du_r8a7795_info },
{ .compatible = "renesas,du-r8a7796", .data = &rcar_du_r8a7796_info },
{ }
};

Expand Down Expand Up @@ -283,7 +330,6 @@ static int rcar_du_remove(struct platform_device *pdev)

drm_kms_helper_poll_fini(ddev);
drm_mode_config_cleanup(ddev);
drm_vblank_cleanup(ddev);

drm_dev_unref(ddev);

Expand All @@ -292,18 +338,12 @@ static int rcar_du_remove(struct platform_device *pdev)

static int rcar_du_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct rcar_du_device *rcdu;
struct drm_device *ddev;
struct resource *mem;
int ret;

if (np == NULL) {
dev_err(&pdev->dev, "no device tree node\n");
return -ENODEV;
}

/* Allocate and initialize the DRM and R-Car device structures. */
/* Allocate and initialize the R-Car device structure. */
rcdu = devm_kzalloc(&pdev->dev, sizeof(*rcdu), GFP_KERNEL);
if (rcdu == NULL)
return -ENOMEM;
Expand All @@ -313,31 +353,22 @@ static int rcar_du_probe(struct platform_device *pdev)
rcdu->dev = &pdev->dev;
rcdu->info = of_match_device(rcar_du_of_table, rcdu->dev)->data;

ddev = drm_dev_alloc(&rcar_du_driver, &pdev->dev);
if (IS_ERR(ddev))
return PTR_ERR(ddev);

rcdu->ddev = ddev;
ddev->dev_private = rcdu;

platform_set_drvdata(pdev, rcdu);

/* I/O resources */
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(rcdu->mmio)) {
ret = PTR_ERR(rcdu->mmio);
goto error;
}

/* Initialize vertical blanking interrupts handling. Start with vblank
* disabled for all CRTCs.
*/
ret = drm_vblank_init(ddev, (1 << rcdu->info->num_crtcs) - 1);
if (ret < 0)
goto error;
if (IS_ERR(rcdu->mmio))
return PTR_ERR(rcdu->mmio);

/* DRM/KMS objects */
ddev = drm_dev_alloc(&rcar_du_driver, &pdev->dev);
if (IS_ERR(ddev))
return PTR_ERR(ddev);

rcdu->ddev = ddev;
ddev->dev_private = rcdu;

ret = rcar_du_modeset_init(rcdu);
if (ret < 0) {
if (ret != -EPROBE_DEFER)
Expand Down
22 changes: 13 additions & 9 deletions drivers/gpu/drm/rcar-du/rcar_du_group.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,16 +105,20 @@ static void rcar_du_group_setup(struct rcar_du_group *rgrp)
if (rcar_du_has(rgrp->dev, RCAR_DU_FEATURE_EXT_CTRL_REGS)) {
rcar_du_group_setup_defr8(rgrp);

/* Configure input dot clock routing. We currently hardcode the
* configuration to routing DOTCLKINn to DUn.
/*
* Configure input dot clock routing. We currently hardcode the
* configuration to routing DOTCLKINn to DUn. Register fields
* depend on the DU generation, but the resulting value is 0 in
* all cases.
*
* On Gen2 a single register in the first group controls dot
* clock selection for all channels, while on Gen3 dot clocks
* are setup through per-group registers, only available when
* the group has two channels.
*/
rcar_du_group_write(rgrp, DIDSR, DIDSR_CODE |
DIDSR_LCDS_DCLKIN(2) |
DIDSR_LCDS_DCLKIN(1) |
DIDSR_LCDS_DCLKIN(0) |
DIDSR_PDCS_CLK(2, 0) |
DIDSR_PDCS_CLK(1, 0) |
DIDSR_PDCS_CLK(0, 0));
if ((rcdu->info->gen < 3 && rgrp->index == 0) ||
(rcdu->info->gen == 3 && rgrp->num_crtcs > 1))
rcar_du_group_write(rgrp, DIDSR, DIDSR_CODE);
}

if (rcdu->info->gen >= 3)
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/rcar-du/rcar_du_hdmienc.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
if (hdmienc == NULL)
return -ENOMEM;

/* Locate drm bridge from the hdmi encoder DT node */
/* Locate the DRM bridge from the HDMI encoder DT node. */
bridge = of_drm_find_bridge(np);
if (!bridge)
return -EPROBE_DEFER;
Expand All @@ -123,7 +123,7 @@ int rcar_du_hdmienc_init(struct rcar_du_device *rcdu,
renc->hdmi = hdmienc;
hdmienc->renc = renc;

/* Link drm_bridge to encoder */
/* Link the bridge to the encoder. */
bridge->encoder = encoder;
encoder->bridge = bridge;

Expand Down
17 changes: 12 additions & 5 deletions drivers/gpu/drm/rcar-du/rcar_du_kms.c
Original file line number Diff line number Diff line change
Expand Up @@ -454,13 +454,13 @@ static int rcar_du_encoders_init_one(struct rcar_du_device *rcdu,
}

ret = rcar_du_encoder_init(rcdu, enc_type, output, encoder, connector);
of_node_put(encoder);
of_node_put(connector);

if (ret && ret != -EPROBE_DEFER)
dev_warn(rcdu->dev,
"failed to initialize encoder %s (%d), skipping\n",
encoder->full_name, ret);
"failed to initialize encoder %s on output %u (%d), skipping\n",
of_node_full_name(encoder), output, ret);

of_node_put(encoder);
of_node_put(connector);

return ret;
}
Expand Down Expand Up @@ -568,6 +568,13 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
if (ret < 0)
return ret;

/* Initialize vertical blanking interrupts handling. Start with vblank
* disabled for all CRTCs.
*/
ret = drm_vblank_init(dev, (1 << rcdu->info->num_crtcs) - 1);
if (ret < 0)
return ret;

/* Initialize the groups. */
num_groups = DIV_ROUND_UP(rcdu->num_crtcs, 2);

Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ static const struct drm_connector_funcs connector_funcs = {

int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
struct rcar_du_encoder *renc,
/* TODO const */ struct device_node *np)
const struct device_node *np)
{
struct drm_encoder *encoder = rcar_encoder_to_drm_encoder(renc);
struct rcar_du_lvds_connector *lvdscon;
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/rcar-du/rcar_du_lvdscon.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ struct rcar_du_encoder;

int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
struct rcar_du_encoder *renc,
struct device_node *np);
const struct device_node *np);

#endif /* __RCAR_DU_LVDSCON_H__ */
19 changes: 9 additions & 10 deletions drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,14 @@ static void rcar_du_lvdsenc_start_gen3(struct rcar_du_lvdsenc *lvds,

rcar_lvds_write(lvds, LVDPLLCR, pllcr);

/* Turn the PLL on, set it to LVDS normal mode, wait for the startup
/* Turn all the channels on. */
rcar_lvds_write(lvds, LVDCR1,
LVDCR1_CHSTBY_GEN3(3) | LVDCR1_CHSTBY_GEN3(2) |
LVDCR1_CHSTBY_GEN3(1) | LVDCR1_CHSTBY_GEN3(0) |
LVDCR1_CLKSTBY_GEN3);

/*
* Turn the PLL on, set it to LVDS normal mode, wait for the startup
* delay and turn the output on.
*/
lvdcr0 = LVDCR0_PLLON;
Expand All @@ -117,12 +124,6 @@ static void rcar_du_lvdsenc_start_gen3(struct rcar_du_lvdsenc *lvds,

lvdcr0 |= LVDCR0_LVRES;
rcar_lvds_write(lvds, LVDCR0, lvdcr0);

/* Turn all the channels on. */
rcar_lvds_write(lvds, LVDCR1,
LVDCR1_CHSTBY_GEN3(3) | LVDCR1_CHSTBY_GEN3(2) |
LVDCR1_CHSTBY_GEN3(1) | LVDCR1_CHSTBY_GEN3(0) |
LVDCR1_CLKSTBY_GEN3);
}

static int rcar_du_lvdsenc_start(struct rcar_du_lvdsenc *lvds,
Expand Down Expand Up @@ -241,10 +242,8 @@ int rcar_du_lvdsenc_init(struct rcar_du_device *rcdu)

for (i = 0; i < rcdu->info->num_lvds; ++i) {
lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL);
if (lvds == NULL) {
dev_err(&pdev->dev, "failed to allocate private data\n");
if (lvds == NULL)
return -ENOMEM;
}

lvds->dev = rcdu;
lvds->index = i;
Expand Down
6 changes: 3 additions & 3 deletions drivers/video/of_display_timing.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ static int of_parse_display_timing(const struct device_node *np,
* @name: name of the timing node
* @dt: display_timing struct to fill
**/
int of_get_display_timing(struct device_node *np, const char *name,
int of_get_display_timing(const struct device_node *np, const char *name,
struct display_timing *dt)
{
struct device_node *timing_np;
Expand All @@ -142,7 +142,7 @@ EXPORT_SYMBOL_GPL(of_get_display_timing);
* of_get_display_timings - parse all display_timing entries from a device_node
* @np: device_node with the subnodes
**/
struct display_timings *of_get_display_timings(struct device_node *np)
struct display_timings *of_get_display_timings(const struct device_node *np)
{
struct device_node *timings_np;
struct device_node *entry;
Expand Down Expand Up @@ -258,7 +258,7 @@ EXPORT_SYMBOL_GPL(of_get_display_timings);
* of_display_timings_exist - check if a display-timings node is provided
* @np: device_node with the timing
**/
int of_display_timings_exist(struct device_node *np)
int of_display_timings_exist(const struct device_node *np)
{
struct device_node *timings_np;

Expand Down
15 changes: 8 additions & 7 deletions include/video/of_display_timing.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,22 @@ struct display_timings;
#define OF_USE_NATIVE_MODE -1

#ifdef CONFIG_OF
int of_get_display_timing(struct device_node *np, const char *name,
int of_get_display_timing(const struct device_node *np, const char *name,
struct display_timing *dt);
struct display_timings *of_get_display_timings(struct device_node *np);
int of_display_timings_exist(struct device_node *np);
struct display_timings *of_get_display_timings(const struct device_node *np);
int of_display_timings_exist(const struct device_node *np);
#else
static inline int of_get_display_timing(struct device_node *np, const char *name,
struct display_timing *dt)
static inline int of_get_display_timing(const struct device_node *np,
const char *name, struct display_timing *dt)
{
return -ENOSYS;
}
static inline struct display_timings *of_get_display_timings(struct device_node *np)
static inline struct display_timings *
of_get_display_timings(const struct device_node *np)
{
return NULL;
}
static inline int of_display_timings_exist(struct device_node *np)
static inline int of_display_timings_exist(const struct device_node *np)
{
return -ENOSYS;
}
Expand Down

0 comments on commit 1a3865d

Please sign in to comment.