提交 5e501ed7 编写于 作者: P Philipp Zabel

drm/imx: imx-ldb: allow to determine bus format from the connected panel

This patch makes the fsl,data-width and fsl,data-mapping device tree
properties optional if a panel is connected to the ldb output port
via the of_graph bindings. The data mapping is determined from the
display_info.bus_format field provided by the panel.
Signed-off-by: NPhilipp Zabel <p.zabel@pengutronix.de>
上级 3973aff0
...@@ -63,6 +63,7 @@ struct imx_ldb_channel { ...@@ -63,6 +63,7 @@ struct imx_ldb_channel {
int edid_len; int edid_len;
struct drm_display_mode mode; struct drm_display_mode mode;
int mode_valid; int mode_valid;
int bus_format;
}; };
struct bus_mux { struct bus_mux {
...@@ -96,7 +97,11 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector) ...@@ -96,7 +97,11 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector)
if (imx_ldb_ch->panel && imx_ldb_ch->panel->funcs && if (imx_ldb_ch->panel && imx_ldb_ch->panel->funcs &&
imx_ldb_ch->panel->funcs->get_modes) { imx_ldb_ch->panel->funcs->get_modes) {
struct drm_display_info *di = &connector->display_info;
num_modes = imx_ldb_ch->panel->funcs->get_modes(imx_ldb_ch->panel); num_modes = imx_ldb_ch->panel->funcs->get_modes(imx_ldb_ch->panel);
if (!imx_ldb_ch->bus_format && di->num_bus_formats)
imx_ldb_ch->bus_format = di->bus_formats[0];
if (num_modes > 0) if (num_modes > 0)
return num_modes; return num_modes;
} }
...@@ -173,21 +178,33 @@ static void imx_ldb_encoder_prepare(struct drm_encoder *encoder) ...@@ -173,21 +178,33 @@ static void imx_ldb_encoder_prepare(struct drm_encoder *encoder)
{ {
struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder); struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder);
struct imx_ldb *ldb = imx_ldb_ch->ldb; struct imx_ldb *ldb = imx_ldb_ch->ldb;
int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN;
u32 bus_format; u32 bus_format;
switch (imx_ldb_ch->chno) { switch (imx_ldb_ch->bus_format) {
case 0: default:
bus_format = (ldb->ldb_ctrl & LDB_DATA_WIDTH_CH0_24) ? dev_warn(ldb->dev,
MEDIA_BUS_FMT_RGB888_1X24 : MEDIA_BUS_FMT_RGB666_1X18; "could not determine data mapping, default to 18-bit \"spwg\"\n");
/* fallthrough */
case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
bus_format = MEDIA_BUS_FMT_RGB666_1X18;
break; break;
case 1: case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
bus_format = (ldb->ldb_ctrl & LDB_DATA_WIDTH_CH1_24) ? bus_format = MEDIA_BUS_FMT_RGB888_1X24;
MEDIA_BUS_FMT_RGB888_1X24 : MEDIA_BUS_FMT_RGB666_1X18; if (imx_ldb_ch->chno == 0 || dual)
ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24;
if (imx_ldb_ch->chno == 1 || dual)
ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24;
break; break;
default: case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
dev_err(ldb->dev, "unable to config di%d panel format\n",
imx_ldb_ch->chno);
bus_format = MEDIA_BUS_FMT_RGB888_1X24; bus_format = MEDIA_BUS_FMT_RGB888_1X24;
if (imx_ldb_ch->chno == 0 || dual)
ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24 |
LDB_BIT_MAP_CH0_JEIDA;
if (imx_ldb_ch->chno == 1 || dual)
ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24 |
LDB_BIT_MAP_CH1_JEIDA;
break;
} }
imx_drm_set_bus_format(encoder, bus_format); imx_drm_set_bus_format(encoder, bus_format);
...@@ -426,25 +443,39 @@ enum { ...@@ -426,25 +443,39 @@ enum {
LVDS_BIT_MAP_JEIDA LVDS_BIT_MAP_JEIDA
}; };
static const char * const imx_ldb_bit_mappings[] = { struct imx_ldb_bit_mapping {
[LVDS_BIT_MAP_SPWG] = "spwg", u32 bus_format;
[LVDS_BIT_MAP_JEIDA] = "jeida", u32 datawidth;
const char * const mapping;
}; };
static const int of_get_data_mapping(struct device_node *np) static const struct imx_ldb_bit_mapping imx_ldb_bit_mappings[] = {
{ MEDIA_BUS_FMT_RGB666_1X7X3_SPWG, 18, "spwg" },
{ MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, 24, "spwg" },
{ MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA, 24, "jeida" },
};
static u32 of_get_bus_format(struct device *dev, struct device_node *np)
{ {
const char *bm; const char *bm;
u32 datawidth = 0;
int ret, i; int ret, i;
ret = of_property_read_string(np, "fsl,data-mapping", &bm); ret = of_property_read_string(np, "fsl,data-mapping", &bm);
if (ret < 0) if (ret < 0)
return ret; return ret;
for (i = 0; i < ARRAY_SIZE(imx_ldb_bit_mappings); i++) of_property_read_u32(np, "fsl,data-width", &datawidth);
if (!strcasecmp(bm, imx_ldb_bit_mappings[i]))
return i; for (i = 0; i < ARRAY_SIZE(imx_ldb_bit_mappings); i++) {
if (!strcasecmp(bm, imx_ldb_bit_mappings[i].mapping) &&
datawidth == imx_ldb_bit_mappings[i].datawidth)
return imx_ldb_bit_mappings[i].bus_format;
}
dev_err(dev, "invalid data mapping: %d-bit \"%s\"\n", datawidth, bm);
return -EINVAL; return -ENOENT;
} }
static struct bus_mux imx6q_lvds_mux[2] = { static struct bus_mux imx6q_lvds_mux[2] = {
...@@ -481,8 +512,6 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) ...@@ -481,8 +512,6 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
struct device_node *child; struct device_node *child;
const u8 *edidp; const u8 *edidp;
struct imx_ldb *imx_ldb; struct imx_ldb *imx_ldb;
int datawidth;
int mapping;
int dual; int dual;
int ret; int ret;
int i; int i;
...@@ -583,39 +612,20 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) ...@@ -583,39 +612,20 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
channel->mode_valid = 1; channel->mode_valid = 1;
} }
ret = of_property_read_u32(child, "fsl,data-width", &datawidth); channel->bus_format = of_get_bus_format(dev, child);
if (ret) if (channel->bus_format == -EINVAL) {
datawidth = 0; /*
else if (datawidth != 18 && datawidth != 24) * If no bus format was specified in the device tree,
return -EINVAL; * we can still get it from the connected panel later.
*/
mapping = of_get_data_mapping(child); if (channel->panel && channel->panel->funcs &&
switch (mapping) { channel->panel->funcs->get_modes)
case LVDS_BIT_MAP_SPWG: channel->bus_format = 0;
if (datawidth == 24) { }
if (i == 0 || dual) if (channel->bus_format < 0) {
imx_ldb->ldb_ctrl |= dev_err(dev, "could not determine data mapping: %d\n",
LDB_DATA_WIDTH_CH0_24; channel->bus_format);
if (i == 1 || dual) return channel->bus_format;
imx_ldb->ldb_ctrl |=
LDB_DATA_WIDTH_CH1_24;
}
break;
case LVDS_BIT_MAP_JEIDA:
if (datawidth == 18) {
dev_err(dev, "JEIDA standard only supported in 24 bit\n");
return -EINVAL;
}
if (i == 0 || dual)
imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24 |
LDB_BIT_MAP_CH0_JEIDA;
if (i == 1 || dual)
imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24 |
LDB_BIT_MAP_CH1_JEIDA;
break;
default:
dev_err(dev, "data mapping not specified or invalid\n");
return -EINVAL;
} }
ret = imx_ldb_register(drm, channel); ret = imx_ldb_register(drm, channel);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册