mirror of
https://github.com/torvalds/linux.git
synced 2024-12-28 13:51:44 +00:00
drm: rcar-du: Add support for LVDS mode selection
Retrieve the LVDS mode from the panel and configure the LVDS encoder accordingly. LVDS mode selection is static as LVDS panels can't be hot-plugged on any of the device supported by the driver. Support for dynamic mode selection can be implemented in the future when needed. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
This commit is contained in:
parent
bf7149f342
commit
e947eccbeb
@ -98,6 +98,8 @@ static void rcar_du_encoder_mode_set(struct drm_encoder *encoder,
|
|||||||
struct drm_connector_state *conn_state)
|
struct drm_connector_state *conn_state)
|
||||||
{
|
{
|
||||||
struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
|
struct rcar_du_encoder *renc = to_rcar_encoder(encoder);
|
||||||
|
struct drm_display_info *info = &conn_state->connector->display_info;
|
||||||
|
enum rcar_lvds_mode mode;
|
||||||
|
|
||||||
rcar_du_crtc_route_output(crtc_state->crtc, renc->output);
|
rcar_du_crtc_route_output(crtc_state->crtc, renc->output);
|
||||||
|
|
||||||
@ -111,6 +113,31 @@ static void rcar_du_encoder_mode_set(struct drm_encoder *encoder,
|
|||||||
}
|
}
|
||||||
|
|
||||||
renc->connector = to_rcar_connector(conn_state->connector);
|
renc->connector = to_rcar_connector(conn_state->connector);
|
||||||
|
|
||||||
|
if (!info->num_bus_formats || !info->bus_formats) {
|
||||||
|
dev_err(encoder->dev->dev, "no LVDS bus format reported\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (info->bus_formats[0]) {
|
||||||
|
case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
|
||||||
|
case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
|
||||||
|
mode = RCAR_LVDS_MODE_JEIDA;
|
||||||
|
break;
|
||||||
|
case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
|
||||||
|
mode = RCAR_LVDS_MODE_VESA;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_err(encoder->dev->dev,
|
||||||
|
"unsupported LVDS bus format 0x%04x\n",
|
||||||
|
info->bus_formats[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info->bus_flags & DRM_BUS_FLAG_DATA_LSB_TO_MSB)
|
||||||
|
mode |= RCAR_LVDS_MODE_MIRROR;
|
||||||
|
|
||||||
|
rcar_du_lvdsenc_set_mode(renc->lvds, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
|
static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
|
||||||
|
@ -31,6 +31,7 @@ struct rcar_du_lvdsenc {
|
|||||||
bool enabled;
|
bool enabled;
|
||||||
|
|
||||||
enum rcar_lvds_input input;
|
enum rcar_lvds_input input;
|
||||||
|
enum rcar_lvds_mode mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void rcar_lvds_write(struct rcar_du_lvdsenc *lvds, u32 reg, u32 data)
|
static void rcar_lvds_write(struct rcar_du_lvdsenc *lvds, u32 reg, u32 data)
|
||||||
@ -61,7 +62,7 @@ static void rcar_du_lvdsenc_start_gen2(struct rcar_du_lvdsenc *lvds,
|
|||||||
/* Select the input, hardcode mode 0, enable LVDS operation and turn
|
/* Select the input, hardcode mode 0, enable LVDS operation and turn
|
||||||
* bias circuitry on.
|
* bias circuitry on.
|
||||||
*/
|
*/
|
||||||
lvdcr0 = LVDCR0_BEN | LVDCR0_LVEN;
|
lvdcr0 = (lvds->mode << LVDCR0_LVMD_SHIFT) | LVDCR0_BEN | LVDCR0_LVEN;
|
||||||
if (rcrtc->index == 2)
|
if (rcrtc->index == 2)
|
||||||
lvdcr0 |= LVDCR0_DUSEL;
|
lvdcr0 |= LVDCR0_DUSEL;
|
||||||
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
|
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
|
||||||
@ -114,7 +115,7 @@ static void rcar_du_lvdsenc_start_gen3(struct rcar_du_lvdsenc *lvds,
|
|||||||
* Turn the PLL on, set it to LVDS normal mode, wait for the startup
|
* Turn the PLL on, set it to LVDS normal mode, wait for the startup
|
||||||
* delay and turn the output on.
|
* delay and turn the output on.
|
||||||
*/
|
*/
|
||||||
lvdcr0 = LVDCR0_PLLON;
|
lvdcr0 = (lvds->mode << LVDCR0_LVMD_SHIFT) | LVDCR0_PLLON;
|
||||||
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
|
rcar_lvds_write(lvds, LVDCR0, lvdcr0);
|
||||||
|
|
||||||
lvdcr0 |= LVDCR0_PWD;
|
lvdcr0 |= LVDCR0_PWD;
|
||||||
@ -211,6 +212,12 @@ void rcar_du_lvdsenc_atomic_check(struct rcar_du_lvdsenc *lvds,
|
|||||||
mode->clock = clamp(mode->clock, 25175, 148500);
|
mode->clock = clamp(mode->clock, 25175, 148500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rcar_du_lvdsenc_set_mode(struct rcar_du_lvdsenc *lvds,
|
||||||
|
enum rcar_lvds_mode mode)
|
||||||
|
{
|
||||||
|
lvds->mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
static int rcar_du_lvdsenc_get_resources(struct rcar_du_lvdsenc *lvds,
|
static int rcar_du_lvdsenc_get_resources(struct rcar_du_lvdsenc *lvds,
|
||||||
struct platform_device *pdev)
|
struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
|
@ -26,8 +26,17 @@ enum rcar_lvds_input {
|
|||||||
RCAR_LVDS_INPUT_DU2,
|
RCAR_LVDS_INPUT_DU2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Keep in sync with the LVDCR0.LVMD hardware register values. */
|
||||||
|
enum rcar_lvds_mode {
|
||||||
|
RCAR_LVDS_MODE_JEIDA = 0,
|
||||||
|
RCAR_LVDS_MODE_MIRROR = 1,
|
||||||
|
RCAR_LVDS_MODE_VESA = 4,
|
||||||
|
};
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_DRM_RCAR_LVDS)
|
#if IS_ENABLED(CONFIG_DRM_RCAR_LVDS)
|
||||||
int rcar_du_lvdsenc_init(struct rcar_du_device *rcdu);
|
int rcar_du_lvdsenc_init(struct rcar_du_device *rcdu);
|
||||||
|
void rcar_du_lvdsenc_set_mode(struct rcar_du_lvdsenc *lvds,
|
||||||
|
enum rcar_lvds_mode mode);
|
||||||
int rcar_du_lvdsenc_enable(struct rcar_du_lvdsenc *lvds,
|
int rcar_du_lvdsenc_enable(struct rcar_du_lvdsenc *lvds,
|
||||||
struct drm_crtc *crtc, bool enable);
|
struct drm_crtc *crtc, bool enable);
|
||||||
void rcar_du_lvdsenc_atomic_check(struct rcar_du_lvdsenc *lvds,
|
void rcar_du_lvdsenc_atomic_check(struct rcar_du_lvdsenc *lvds,
|
||||||
@ -37,6 +46,10 @@ static inline int rcar_du_lvdsenc_init(struct rcar_du_device *rcdu)
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
static inline void rcar_du_lvdsenc_set_mode(struct rcar_du_lvdsenc *lvds,
|
||||||
|
enum rcar_lvds_mode mode)
|
||||||
|
{
|
||||||
|
}
|
||||||
static inline int rcar_du_lvdsenc_enable(struct rcar_du_lvdsenc *lvds,
|
static inline int rcar_du_lvdsenc_enable(struct rcar_du_lvdsenc *lvds,
|
||||||
struct drm_crtc *crtc, bool enable)
|
struct drm_crtc *crtc, bool enable)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user