Commit 23370918 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'du-next-20190328' of git://linuxtv.org/pinchartl/media into drm-next

R-Car DU miscellaneous changes for v5.2
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190328042035.GA4846@pendragon.ideasonboard.com
parents e0a3def2 00d082cc
...@@ -32,21 +32,21 @@ ...@@ -32,21 +32,21 @@
static u32 rcar_du_crtc_read(struct rcar_du_crtc *rcrtc, u32 reg) static u32 rcar_du_crtc_read(struct rcar_du_crtc *rcrtc, u32 reg)
{ {
struct rcar_du_device *rcdu = rcrtc->group->dev; struct rcar_du_device *rcdu = rcrtc->dev;
return rcar_du_read(rcdu, rcrtc->mmio_offset + reg); return rcar_du_read(rcdu, rcrtc->mmio_offset + reg);
} }
static void rcar_du_crtc_write(struct rcar_du_crtc *rcrtc, u32 reg, u32 data) static void rcar_du_crtc_write(struct rcar_du_crtc *rcrtc, u32 reg, u32 data)
{ {
struct rcar_du_device *rcdu = rcrtc->group->dev; struct rcar_du_device *rcdu = rcrtc->dev;
rcar_du_write(rcdu, rcrtc->mmio_offset + reg, data); rcar_du_write(rcdu, rcrtc->mmio_offset + reg, data);
} }
static void rcar_du_crtc_clr(struct rcar_du_crtc *rcrtc, u32 reg, u32 clr) static void rcar_du_crtc_clr(struct rcar_du_crtc *rcrtc, u32 reg, u32 clr)
{ {
struct rcar_du_device *rcdu = rcrtc->group->dev; struct rcar_du_device *rcdu = rcrtc->dev;
rcar_du_write(rcdu, rcrtc->mmio_offset + reg, rcar_du_write(rcdu, rcrtc->mmio_offset + reg,
rcar_du_read(rcdu, rcrtc->mmio_offset + reg) & ~clr); rcar_du_read(rcdu, rcrtc->mmio_offset + reg) & ~clr);
...@@ -54,7 +54,7 @@ static void rcar_du_crtc_clr(struct rcar_du_crtc *rcrtc, u32 reg, u32 clr) ...@@ -54,7 +54,7 @@ static void rcar_du_crtc_clr(struct rcar_du_crtc *rcrtc, u32 reg, u32 clr)
static void rcar_du_crtc_set(struct rcar_du_crtc *rcrtc, u32 reg, u32 set) static void rcar_du_crtc_set(struct rcar_du_crtc *rcrtc, u32 reg, u32 set)
{ {
struct rcar_du_device *rcdu = rcrtc->group->dev; struct rcar_du_device *rcdu = rcrtc->dev;
rcar_du_write(rcdu, rcrtc->mmio_offset + reg, rcar_du_write(rcdu, rcrtc->mmio_offset + reg,
rcar_du_read(rcdu, rcrtc->mmio_offset + reg) | set); rcar_du_read(rcdu, rcrtc->mmio_offset + reg) | set);
...@@ -62,7 +62,7 @@ static void rcar_du_crtc_set(struct rcar_du_crtc *rcrtc, u32 reg, u32 set) ...@@ -62,7 +62,7 @@ static void rcar_du_crtc_set(struct rcar_du_crtc *rcrtc, u32 reg, u32 set)
void rcar_du_crtc_dsysr_clr_set(struct rcar_du_crtc *rcrtc, u32 clr, u32 set) void rcar_du_crtc_dsysr_clr_set(struct rcar_du_crtc *rcrtc, u32 clr, u32 set)
{ {
struct rcar_du_device *rcdu = rcrtc->group->dev; struct rcar_du_device *rcdu = rcrtc->dev;
rcrtc->dsysr = (rcrtc->dsysr & ~clr) | set; rcrtc->dsysr = (rcrtc->dsysr & ~clr) | set;
rcar_du_write(rcdu, rcrtc->mmio_offset + DSYSR, rcrtc->dsysr); rcar_du_write(rcdu, rcrtc->mmio_offset + DSYSR, rcrtc->dsysr);
...@@ -157,10 +157,9 @@ static void rcar_du_dpll_divider(struct rcar_du_crtc *rcrtc, ...@@ -157,10 +157,9 @@ static void rcar_du_dpll_divider(struct rcar_du_crtc *rcrtc,
} }
done: done:
dev_dbg(rcrtc->group->dev->dev, dev_dbg(rcrtc->dev->dev,
"output:%u, fdpll:%u, n:%u, m:%u, diff:%lu\n", "output:%u, fdpll:%u, n:%u, m:%u, diff:%lu\n",
dpll->output, dpll->fdpll, dpll->n, dpll->m, dpll->output, dpll->fdpll, dpll->n, dpll->m, best_diff);
best_diff);
} }
struct du_clk_params { struct du_clk_params {
...@@ -212,7 +211,7 @@ static const struct soc_device_attribute rcar_du_r8a7795_es1[] = { ...@@ -212,7 +211,7 @@ static const struct soc_device_attribute rcar_du_r8a7795_es1[] = {
static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc) static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
{ {
const struct drm_display_mode *mode = &rcrtc->crtc.state->adjusted_mode; const struct drm_display_mode *mode = &rcrtc->crtc.state->adjusted_mode;
struct rcar_du_device *rcdu = rcrtc->group->dev; struct rcar_du_device *rcdu = rcrtc->dev;
unsigned long mode_clock = mode->clock * 1000; unsigned long mode_clock = mode->clock * 1000;
u32 dsmr; u32 dsmr;
u32 escr; u32 escr;
...@@ -277,7 +276,7 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc) ...@@ -277,7 +276,7 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
rcar_du_escr_divider(rcrtc->extclock, mode_clock, rcar_du_escr_divider(rcrtc->extclock, mode_clock,
ESCR_DCLKSEL_DCLKIN, &params); ESCR_DCLKSEL_DCLKIN, &params);
dev_dbg(rcrtc->group->dev->dev, "mode clock %lu %s rate %lu\n", dev_dbg(rcrtc->dev->dev, "mode clock %lu %s rate %lu\n",
mode_clock, params.clk == rcrtc->clock ? "cpg" : "ext", mode_clock, params.clk == rcrtc->clock ? "cpg" : "ext",
params.rate); params.rate);
...@@ -285,7 +284,7 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc) ...@@ -285,7 +284,7 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
escr = params.escr; escr = params.escr;
} }
dev_dbg(rcrtc->group->dev->dev, "%s: ESCR 0x%08x\n", __func__, escr); dev_dbg(rcrtc->dev->dev, "%s: ESCR 0x%08x\n", __func__, escr);
rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? ESCR13 : ESCR02, escr); rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? ESCR13 : ESCR02, escr);
rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? OTAR13 : OTAR02, 0); rcar_du_crtc_write(rcrtc, rcrtc->index % 2 ? OTAR13 : OTAR02, 0);
...@@ -333,7 +332,7 @@ plane_format(struct rcar_du_plane *plane) ...@@ -333,7 +332,7 @@ plane_format(struct rcar_du_plane *plane)
static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc) static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
{ {
struct rcar_du_plane *planes[RCAR_DU_NUM_HW_PLANES]; struct rcar_du_plane *planes[RCAR_DU_NUM_HW_PLANES];
struct rcar_du_device *rcdu = rcrtc->group->dev; struct rcar_du_device *rcdu = rcrtc->dev;
unsigned int num_planes = 0; unsigned int num_planes = 0;
unsigned int dptsr_planes; unsigned int dptsr_planes;
unsigned int hwplanes = 0; unsigned int hwplanes = 0;
...@@ -463,7 +462,7 @@ static bool rcar_du_crtc_page_flip_pending(struct rcar_du_crtc *rcrtc) ...@@ -463,7 +462,7 @@ static bool rcar_du_crtc_page_flip_pending(struct rcar_du_crtc *rcrtc)
static void rcar_du_crtc_wait_page_flip(struct rcar_du_crtc *rcrtc) static void rcar_du_crtc_wait_page_flip(struct rcar_du_crtc *rcrtc)
{ {
struct rcar_du_device *rcdu = rcrtc->group->dev; struct rcar_du_device *rcdu = rcrtc->dev;
if (wait_event_timeout(rcrtc->flip_wait, if (wait_event_timeout(rcrtc->flip_wait,
!rcar_du_crtc_page_flip_pending(rcrtc), !rcar_du_crtc_page_flip_pending(rcrtc),
...@@ -493,7 +492,7 @@ static void rcar_du_crtc_setup(struct rcar_du_crtc *rcrtc) ...@@ -493,7 +492,7 @@ static void rcar_du_crtc_setup(struct rcar_du_crtc *rcrtc)
rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR, 0); rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR, 0);
/* Enable the VSP compositor. */ /* Enable the VSP compositor. */
if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE)) if (rcar_du_has(rcrtc->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
rcar_du_vsp_enable(rcrtc); rcar_du_vsp_enable(rcrtc);
/* Turn vertical blanking interrupt reporting on. */ /* Turn vertical blanking interrupt reporting on. */
...@@ -564,7 +563,7 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc) ...@@ -564,7 +563,7 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
static void rcar_du_crtc_disable_planes(struct rcar_du_crtc *rcrtc) static void rcar_du_crtc_disable_planes(struct rcar_du_crtc *rcrtc)
{ {
struct rcar_du_device *rcdu = rcrtc->group->dev; struct rcar_du_device *rcdu = rcrtc->dev;
struct drm_crtc *crtc = &rcrtc->crtc; struct drm_crtc *crtc = &rcrtc->crtc;
u32 status; u32 status;
...@@ -617,7 +616,7 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc) ...@@ -617,7 +616,7 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
drm_crtc_vblank_off(crtc); drm_crtc_vblank_off(crtc);
/* Disable the VSP compositor. */ /* Disable the VSP compositor. */
if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE)) if (rcar_du_has(rcrtc->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
rcar_du_vsp_disable(rcrtc); rcar_du_vsp_disable(rcrtc);
/* /*
...@@ -627,7 +626,7 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc) ...@@ -627,7 +626,7 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
* TODO: Find another way to stop the display for DUs that don't support * TODO: Find another way to stop the display for DUs that don't support
* TVM sync. * TVM sync.
*/ */
if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_TVM_SYNC)) if (rcar_du_has(rcrtc->dev, RCAR_DU_FEATURE_TVM_SYNC))
rcar_du_crtc_dsysr_clr_set(rcrtc, DSYSR_TVM_MASK, rcar_du_crtc_dsysr_clr_set(rcrtc, DSYSR_TVM_MASK,
DSYSR_TVM_SWITCH); DSYSR_TVM_SWITCH);
...@@ -666,7 +665,7 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc, ...@@ -666,7 +665,7 @@ static void rcar_du_crtc_atomic_enable(struct drm_crtc *crtc,
{ {
struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
struct rcar_du_crtc_state *rstate = to_rcar_crtc_state(crtc->state); struct rcar_du_crtc_state *rstate = to_rcar_crtc_state(crtc->state);
struct rcar_du_device *rcdu = rcrtc->group->dev; struct rcar_du_device *rcdu = rcrtc->dev;
rcar_du_crtc_get(rcrtc); rcar_du_crtc_get(rcrtc);
...@@ -694,7 +693,7 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc, ...@@ -694,7 +693,7 @@ static void rcar_du_crtc_atomic_disable(struct drm_crtc *crtc,
{ {
struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
struct rcar_du_crtc_state *rstate = to_rcar_crtc_state(old_state); struct rcar_du_crtc_state *rstate = to_rcar_crtc_state(old_state);
struct rcar_du_device *rcdu = rcrtc->group->dev; struct rcar_du_device *rcdu = rcrtc->dev;
rcar_du_crtc_stop(rcrtc); rcar_du_crtc_stop(rcrtc);
rcar_du_crtc_put(rcrtc); rcar_du_crtc_put(rcrtc);
...@@ -740,7 +739,7 @@ static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc, ...@@ -740,7 +739,7 @@ static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc,
*/ */
rcar_du_crtc_get(rcrtc); rcar_du_crtc_get(rcrtc);
if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE)) if (rcar_du_has(rcrtc->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
rcar_du_vsp_atomic_begin(rcrtc); rcar_du_vsp_atomic_begin(rcrtc);
} }
...@@ -762,15 +761,16 @@ static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc, ...@@ -762,15 +761,16 @@ static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc,
spin_unlock_irqrestore(&dev->event_lock, flags); spin_unlock_irqrestore(&dev->event_lock, flags);
} }
if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE)) if (rcar_du_has(rcrtc->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
rcar_du_vsp_atomic_flush(rcrtc); rcar_du_vsp_atomic_flush(rcrtc);
} }
enum drm_mode_status rcar_du_crtc_mode_valid(struct drm_crtc *crtc, static enum drm_mode_status
const struct drm_display_mode *mode) rcar_du_crtc_mode_valid(struct drm_crtc *crtc,
const struct drm_display_mode *mode)
{ {
struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
struct rcar_du_device *rcdu = rcrtc->group->dev; struct rcar_du_device *rcdu = rcrtc->dev;
bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
unsigned int vbp; unsigned int vbp;
...@@ -802,7 +802,7 @@ static const struct drm_crtc_helper_funcs crtc_helper_funcs = { ...@@ -802,7 +802,7 @@ static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
static void rcar_du_crtc_crc_init(struct rcar_du_crtc *rcrtc) static void rcar_du_crtc_crc_init(struct rcar_du_crtc *rcrtc)
{ {
struct rcar_du_device *rcdu = rcrtc->group->dev; struct rcar_du_device *rcdu = rcrtc->dev;
const char **sources; const char **sources;
unsigned int count; unsigned int count;
int i = -1; int i = -1;
...@@ -986,8 +986,8 @@ static int rcar_du_crtc_verify_crc_source(struct drm_crtc *crtc, ...@@ -986,8 +986,8 @@ static int rcar_du_crtc_verify_crc_source(struct drm_crtc *crtc,
return 0; return 0;
} }
const char *const *rcar_du_crtc_get_crc_sources(struct drm_crtc *crtc, static const char *const *
size_t *count) rcar_du_crtc_get_crc_sources(struct drm_crtc *crtc, size_t *count)
{ {
struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
...@@ -1084,7 +1084,7 @@ static const struct drm_crtc_funcs crtc_funcs_gen3 = { ...@@ -1084,7 +1084,7 @@ static const struct drm_crtc_funcs crtc_funcs_gen3 = {
static irqreturn_t rcar_du_crtc_irq(int irq, void *arg) static irqreturn_t rcar_du_crtc_irq(int irq, void *arg)
{ {
struct rcar_du_crtc *rcrtc = arg; struct rcar_du_crtc *rcrtc = arg;
struct rcar_du_device *rcdu = rcrtc->group->dev; struct rcar_du_device *rcdu = rcrtc->dev;
irqreturn_t ret = IRQ_NONE; irqreturn_t ret = IRQ_NONE;
u32 status; u32 status;
...@@ -1176,6 +1176,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int swindex, ...@@ -1176,6 +1176,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int swindex,
init_waitqueue_head(&rcrtc->vblank_wait); init_waitqueue_head(&rcrtc->vblank_wait);
spin_lock_init(&rcrtc->vblank_lock); spin_lock_init(&rcrtc->vblank_lock);
rcrtc->dev = rcdu;
rcrtc->group = rgrp; rcrtc->group = rgrp;
rcrtc->mmio_offset = mmio_offsets[hwindex]; rcrtc->mmio_offset = mmio_offsets[hwindex];
rcrtc->index = hwindex; rcrtc->index = hwindex;
......
...@@ -25,6 +25,7 @@ struct rcar_du_vsp; ...@@ -25,6 +25,7 @@ struct rcar_du_vsp;
/** /**
* struct rcar_du_crtc - the CRTC, representing a DU superposition processor * struct rcar_du_crtc - the CRTC, representing a DU superposition processor
* @crtc: base DRM CRTC * @crtc: base DRM CRTC
* @dev: the DU device
* @clock: the CRTC functional clock * @clock: the CRTC functional clock
* @extclock: external pixel dot clock (optional) * @extclock: external pixel dot clock (optional)
* @mmio_offset: offset of the CRTC registers in the DU MMIO block * @mmio_offset: offset of the CRTC registers in the DU MMIO block
...@@ -45,6 +46,7 @@ struct rcar_du_vsp; ...@@ -45,6 +46,7 @@ struct rcar_du_vsp;
struct rcar_du_crtc { struct rcar_du_crtc {
struct drm_crtc crtc; struct drm_crtc crtc;
struct rcar_du_device *dev;
struct clk *clock; struct clk *clock;
struct clk *extclock; struct clk *extclock;
unsigned int mmio_offset; unsigned int mmio_offset;
...@@ -102,8 +104,6 @@ enum rcar_du_output { ...@@ -102,8 +104,6 @@ enum rcar_du_output {
int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int swindex, int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int swindex,
unsigned int hwindex); unsigned int hwindex);
void rcar_du_crtc_suspend(struct rcar_du_crtc *rcrtc);
void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc);
void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc); void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc);
......
...@@ -28,13 +28,33 @@ static const struct drm_encoder_funcs encoder_funcs = { ...@@ -28,13 +28,33 @@ static const struct drm_encoder_funcs encoder_funcs = {
.destroy = drm_encoder_cleanup, .destroy = drm_encoder_cleanup,
}; };
static unsigned int rcar_du_encoder_count_ports(struct device_node *node)
{
struct device_node *ports;
struct device_node *port;
unsigned int num_ports = 0;
ports = of_get_child_by_name(node, "ports");
if (!ports)
ports = of_node_get(node);
for_each_child_of_node(ports, port) {
if (of_node_name_eq(port, "port"))
num_ports++;
}
of_node_put(ports);
return num_ports;
}
int rcar_du_encoder_init(struct rcar_du_device *rcdu, int rcar_du_encoder_init(struct rcar_du_device *rcdu,
enum rcar_du_output output, enum rcar_du_output output,
struct device_node *enc_node) struct device_node *enc_node)
{ {
struct rcar_du_encoder *renc; struct rcar_du_encoder *renc;
struct drm_encoder *encoder; struct drm_encoder *encoder;
struct drm_bridge *bridge = NULL; struct drm_bridge *bridge;
int ret; int ret;
renc = devm_kzalloc(rcdu->dev, sizeof(*renc), GFP_KERNEL); renc = devm_kzalloc(rcdu->dev, sizeof(*renc), GFP_KERNEL);
...@@ -48,11 +68,33 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu, ...@@ -48,11 +68,33 @@ int rcar_du_encoder_init(struct rcar_du_device *rcdu,
dev_dbg(rcdu->dev, "initializing encoder %pOF for output %u\n", dev_dbg(rcdu->dev, "initializing encoder %pOF for output %u\n",
enc_node, output); enc_node, output);
/* Locate the DRM bridge from the encoder DT node. */ /*
bridge = of_drm_find_bridge(enc_node); * Locate the DRM bridge from the DT node. For the DPAD outputs, if the
if (!bridge) { * DT node has a single port, assume that it describes a panel and
ret = -EPROBE_DEFER; * create a panel bridge.
goto done; */
if ((output == RCAR_DU_OUTPUT_DPAD0 ||
output == RCAR_DU_OUTPUT_DPAD1) &&
rcar_du_encoder_count_ports(enc_node) == 1) {
struct drm_panel *panel = of_drm_find_panel(enc_node);
if (IS_ERR(panel)) {
ret = PTR_ERR(panel);
goto done;
}
bridge = devm_drm_panel_bridge_add(rcdu->dev, panel,
DRM_MODE_CONNECTOR_DPI);
if (IS_ERR(bridge)) {
ret = PTR_ERR(bridge);
goto done;
}
} else {
bridge = of_drm_find_bridge(enc_node);
if (!bridge) {
ret = -EPROBE_DEFER;
goto done;
}
} }
ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs, ret = drm_encoder_init(rcdu->ddev, encoder, &encoder_funcs,
......
...@@ -47,7 +47,7 @@ static void rcar_du_vsp_complete(void *private, unsigned int status, u32 crc) ...@@ -47,7 +47,7 @@ static void rcar_du_vsp_complete(void *private, unsigned int status, u32 crc)
void rcar_du_vsp_enable(struct rcar_du_crtc *crtc) void rcar_du_vsp_enable(struct rcar_du_crtc *crtc)
{ {
const struct drm_display_mode *mode = &crtc->crtc.state->adjusted_mode; const struct drm_display_mode *mode = &crtc->crtc.state->adjusted_mode;
struct rcar_du_device *rcdu = crtc->group->dev; struct rcar_du_device *rcdu = crtc->dev;
struct vsp1_du_lif_config cfg = { struct vsp1_du_lif_config cfg = {
.width = mode->hdisplay, .width = mode->hdisplay,
.height = mode->vdisplay, .height = mode->vdisplay,
......
...@@ -283,7 +283,7 @@ static void rcar_lvds_d3_e3_pll_calc(struct rcar_lvds *lvds, struct clk *clk, ...@@ -283,7 +283,7 @@ static void rcar_lvds_d3_e3_pll_calc(struct rcar_lvds *lvds, struct clk *clk,
* divider. * divider.
*/ */
fout = fvco / (1 << e) / div7; fout = fvco / (1 << e) / div7;
div = DIV_ROUND_CLOSEST(fout, target); div = max(1UL, DIV_ROUND_CLOSEST(fout, target));
diff = abs(fout / div - target); diff = abs(fout / div - target);
if (diff < pll->diff) { if (diff < pll->diff) {
...@@ -485,9 +485,13 @@ static void rcar_lvds_enable(struct drm_bridge *bridge) ...@@ -485,9 +485,13 @@ static void rcar_lvds_enable(struct drm_bridge *bridge)
} }
if (lvds->info->quirks & RCAR_LVDS_QUIRK_GEN3_LVEN) { if (lvds->info->quirks & RCAR_LVDS_QUIRK_GEN3_LVEN) {
/* Turn on the LVDS PHY. */ /*
* Turn on the LVDS PHY. On D3, the LVEN and LVRES bit must be
* set at the same time, so don't write the register yet.
*/
lvdcr0 |= LVDCR0_LVEN; lvdcr0 |= LVDCR0_LVEN;
rcar_lvds_write(lvds, LVDCR0, lvdcr0); if (!(lvds->info->quirks & RCAR_LVDS_QUIRK_PWD))
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
} }
if (!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)) { if (!(lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL)) {
...@@ -531,11 +535,16 @@ static bool rcar_lvds_mode_fixup(struct drm_bridge *bridge, ...@@ -531,11 +535,16 @@ static bool rcar_lvds_mode_fixup(struct drm_bridge *bridge,
const struct drm_display_mode *mode, const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode) struct drm_display_mode *adjusted_mode)
{ {
struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
int min_freq;
/* /*
* The internal LVDS encoder has a restricted clock frequency operating * The internal LVDS encoder has a restricted clock frequency operating
* range (31MHz to 148.5MHz). Clamp the clock accordingly. * range, from 5MHz to 148.5MHz on D3 and E3, and from 31MHz to
* 148.5MHz on all other platforms. Clamp the clock accordingly.
*/ */
adjusted_mode->clock = clamp(adjusted_mode->clock, 31000, 148500); min_freq = lvds->info->quirks & RCAR_LVDS_QUIRK_EXT_PLL ? 5000 : 31000;
adjusted_mode->clock = clamp(adjusted_mode->clock, min_freq, 148500);
return true; return true;
} }
......
...@@ -78,7 +78,7 @@ struct drm_plane_helper_funcs; ...@@ -78,7 +78,7 @@ struct drm_plane_helper_funcs;
/** /**
* struct drm_crtc_state - mutable CRTC state * struct drm_crtc_state - mutable CRTC state
* *
* Note that the distinction between @enable and @active is rather subtile: * Note that the distinction between @enable and @active is rather subtle:
* Flipping @active while @enable is set without changing anything else may * Flipping @active while @enable is set without changing anything else may
* never return in a failure from the &drm_mode_config_funcs.atomic_check * never return in a failure from the &drm_mode_config_funcs.atomic_check
* callback. Userspace assumes that a DPMS On will always succeed. In other * callback. Userspace assumes that a DPMS On will always succeed. In other
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
struct drm_clip_rect; struct drm_clip_rect;
struct drm_device; struct drm_device;
struct drm_file; struct drm_file;
struct drm_format_info;
struct drm_framebuffer; struct drm_framebuffer;
struct drm_gem_object; struct drm_gem_object;
......
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