video/drm: Merge panel driver into one driver
This merges the rockchip panel driver into the common driver. This will make it easier to share code between the drivers and eventually merge them into one driver. Change-Id: I4c59e5f4f39ffc43b4d0339de8dfa23aec28220b Signed-off-by: Wyon Bi <bivvy.bi@rock-chips.com>
This commit is contained in:
parent
cac6ce1777
commit
c493d00e7c
|
|
@ -10,10 +10,8 @@ menuconfig DRM_ROCKCHIP
|
|||
Rockchip RK3288 and RK3399.
|
||||
|
||||
config DRM_ROCKCHIP_PANEL
|
||||
bool
|
||||
|
||||
config DRM_ROCKCHIP_DSI_PANEL
|
||||
bool
|
||||
bool "Rockchip Panel Support"
|
||||
select DRM_ROCKCHIP_MIPI_DSI
|
||||
|
||||
config DRM_ROCKCHIP_DW_HDMI
|
||||
bool "Rockchip specific extensions for Synopsys DW HDMI"
|
||||
|
|
@ -30,7 +28,7 @@ config DRM_ROCKCHIP_DW_MIPI_DSI
|
|||
tristate "Rockchip specific extensions for Synopsys DW MIPI DSI"
|
||||
depends on DRM_ROCKCHIP
|
||||
select DRM_ROCKCHIP_MIPI_DSI
|
||||
select DRM_ROCKCHIP_DSI_PANEL
|
||||
select DRM_ROCKCHIP_PANEL
|
||||
help
|
||||
This selects support for Rockchip SoC specific extensions
|
||||
for the Synopsys DesignWare HDMI driver. If you want to
|
||||
|
|
|
|||
|
|
@ -5,14 +5,12 @@
|
|||
#
|
||||
|
||||
obj-y += rockchip_display.o rockchip_crtc.o rockchip_phy.o \
|
||||
rockchip_vop.o rockchip_vop_reg.o bmp_helper.o \
|
||||
rockchip_panel.o
|
||||
rockchip_vop.o rockchip_vop_reg.o bmp_helper.o
|
||||
|
||||
obj-$(CONFIG_DRM_ROCKCHIP_MIPI_DSI) += rockchip_mipi_dsi.o
|
||||
obj-$(CONFIG_DRM_ROCKCHIP_DW_MIPI_DSI) += rockchip-dw-mipi-dsi.o \
|
||||
rockchip-inno-mipi-dphy.o rockchip_dsi_panel.o
|
||||
rockchip-inno-mipi-dphy.o
|
||||
obj-$(CONFIG_DRM_ROCKCHIP_DW_HDMI) += rockchip_dw_hdmi.o dw_hdmi.o
|
||||
obj-$(CONFIG_DRM_ROCKCHIP_ANALOGIX_DP) += rockchip_analogix_dp.o rockchip_analogix_dp_reg.o
|
||||
obj-$(CONFIG_DRM_ROCKCHIP_LVDS) += rockchip_lvds.o
|
||||
obj-$(CONFIG_DRM_ROCKCHIP_PANEL) += panel_simple.o
|
||||
obj-$(CONFIG_DRM_ROCKCHIP_DSI_PANEL) += rockchip_dsi_panel.o
|
||||
obj-$(CONFIG_DRM_ROCKCHIP_PANEL) += rockchip_panel.o
|
||||
|
|
|
|||
|
|
@ -1,202 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <common.h>
|
||||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/media-bus-format.h>
|
||||
#include <dm/uclass.h>
|
||||
#include <dm/uclass-id.h>
|
||||
#include <dm/ofnode.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <backlight.h>
|
||||
#include <power/regulator.h>
|
||||
|
||||
#include "rockchip_display.h"
|
||||
#include "rockchip_crtc.h"
|
||||
#include "rockchip_connector.h"
|
||||
#include "rockchip_panel.h"
|
||||
|
||||
#define msleep(a) udelay(a * 1000)
|
||||
|
||||
struct panel_simple {
|
||||
struct udevice *dev;
|
||||
const void *blob;
|
||||
ofnode node;
|
||||
|
||||
const struct drm_display_mode *mode;
|
||||
int bus_format;
|
||||
|
||||
struct udevice *power_supply;
|
||||
bool power_invert;
|
||||
struct udevice *backlight;
|
||||
struct gpio_desc enable;
|
||||
|
||||
int delay_prepare;
|
||||
int delay_unprepare;
|
||||
int delay_enable;
|
||||
int delay_disable;
|
||||
};
|
||||
|
||||
static int panel_simple_prepare(struct display_state *state)
|
||||
{
|
||||
struct panel_state *panel_state = &state->panel_state;
|
||||
struct panel_simple *panel = panel_state->private;
|
||||
int ret;
|
||||
|
||||
if (panel->power_supply) {
|
||||
ret = regulator_set_enable(panel->power_supply,
|
||||
panel->power_invert);
|
||||
if (ret)
|
||||
printf("%s: failed to enable power_supply",
|
||||
__func__);
|
||||
}
|
||||
|
||||
dm_gpio_set_value(&panel->enable, 1);
|
||||
mdelay(panel->delay_prepare);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int panel_simple_unprepare(struct display_state *state)
|
||||
{
|
||||
struct panel_state *panel_state = &state->panel_state;
|
||||
struct panel_simple *panel = panel_state->private;
|
||||
|
||||
dm_gpio_set_value(&panel->enable, 0);
|
||||
mdelay(panel->delay_unprepare);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int panel_simple_enable(struct display_state *state)
|
||||
{
|
||||
struct panel_state *panel_state = &state->panel_state;
|
||||
struct panel_simple *panel = panel_state->private;
|
||||
int ret;
|
||||
|
||||
if (panel->backlight) {
|
||||
ret = backlight_enable(panel->backlight);
|
||||
mdelay(panel->delay_enable);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int panel_simple_disable(struct display_state *state)
|
||||
{
|
||||
struct panel_state *panel_state = &state->panel_state;
|
||||
struct panel_simple *panel = panel_state->private;
|
||||
int ret;
|
||||
|
||||
if (panel->backlight) {
|
||||
ret = backlight_disable(panel->backlight);
|
||||
mdelay(panel->delay_disable);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int panel_simple_parse_dt(const void *blob, ofnode node,
|
||||
struct panel_simple *panel)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = gpio_request_by_name(panel->dev, "enable-gpios", 0,
|
||||
&panel->enable, GPIOD_IS_OUT);
|
||||
if (ret && ret != -ENOENT) {
|
||||
printf("%s: Warning: cannot get enable GPIO: ret=%d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, panel->dev,
|
||||
"backlight", &panel->backlight);
|
||||
if (ret && ret != -ENOENT) {
|
||||
printf("%s: Cannot get backlight: ret=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, panel->dev,
|
||||
"power-supply",
|
||||
&panel->power_supply);
|
||||
if (ret && ret != -ENOENT) {
|
||||
printf("%s: Cannot get power supply: ret=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
panel->power_invert = !!ofnode_read_s32_default(node, "power_invert", 0);
|
||||
|
||||
panel->delay_prepare = ofnode_read_s32_default(node, "prepare-delay-ms", 0);
|
||||
panel->delay_unprepare = ofnode_read_s32_default(node, "unprepare-delay-ms", 0);
|
||||
panel->delay_enable = ofnode_read_s32_default(node, "enable-delay-ms", 0);
|
||||
panel->delay_disable = ofnode_read_s32_default(node, "disable-delay-ms", 0);
|
||||
panel->bus_format = ofnode_read_s32_default(node, "bus-format", MEDIA_BUS_FMT_RBG888_1X24);
|
||||
|
||||
debug("delay prepare[%d] unprepare[%d] enable[%d] disable[%d]\n",
|
||||
panel->delay_prepare, panel->delay_unprepare,
|
||||
panel->delay_enable, panel->delay_disable);
|
||||
|
||||
/* keep panel blank on init. */
|
||||
dm_gpio_set_value(&panel->enable, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int panel_simple_init(struct display_state *state)
|
||||
{
|
||||
const void *blob = state->blob;
|
||||
struct connector_state *conn_state = &state->conn_state;
|
||||
struct panel_state *panel_state = &state->panel_state;
|
||||
ofnode node = panel_state->node;
|
||||
const struct drm_display_mode *mode = panel_state->panel->data;
|
||||
struct panel_simple *panel;
|
||||
int ret;
|
||||
|
||||
panel = malloc(sizeof(*panel));
|
||||
if (!panel)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(panel, 0, sizeof(*panel));
|
||||
panel->blob = blob;
|
||||
panel->node = node;
|
||||
panel->mode = mode;
|
||||
panel->dev = panel_state->dev;
|
||||
panel_state->private = panel;
|
||||
|
||||
ret = panel_simple_parse_dt(blob, node, panel);
|
||||
if (ret) {
|
||||
printf("%s: failed to parse DT\n", __func__);
|
||||
free(panel);
|
||||
return ret;
|
||||
}
|
||||
|
||||
conn_state->bus_format = panel->bus_format;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void panel_simple_deinit(struct display_state *state)
|
||||
{
|
||||
struct panel_state *panel_state = &state->panel_state;
|
||||
struct panel_simple *panel = panel_state->private;
|
||||
|
||||
free(panel);
|
||||
}
|
||||
|
||||
const struct rockchip_panel_funcs panel_simple_funcs = {
|
||||
.init = panel_simple_init,
|
||||
.deinit = panel_simple_deinit,
|
||||
.prepare = panel_simple_prepare,
|
||||
.unprepare = panel_simple_unprepare,
|
||||
.enable = panel_simple_enable,
|
||||
.disable = panel_simple_disable,
|
||||
};
|
||||
|
|
@ -199,11 +199,13 @@ static int connector_panel_init(struct display_state *state)
|
|||
panel_state->dev = dev;
|
||||
panel_state->panel = panel;
|
||||
|
||||
ret = rockchip_panel_init(state);
|
||||
if (panel->funcs && panel->funcs->init) {
|
||||
ret = panel->funcs->init(state);
|
||||
if (ret) {
|
||||
printf("failed to init panel driver\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
dsp_lut_node = dev_read_subnode(dev, "dsp-lut");
|
||||
if (!ofnode_valid(dsp_lut_node)) {
|
||||
|
|
@ -409,31 +411,44 @@ static int display_get_timing(struct display_state *state)
|
|||
struct drm_display_mode *mode = &conn_state->mode;
|
||||
const struct drm_display_mode *m;
|
||||
struct panel_state *panel_state = &state->panel_state;
|
||||
ofnode panel = panel_state->node;
|
||||
const struct rockchip_panel *panel = panel_state->panel;
|
||||
const struct rockchip_panel_funcs *panel_funcs = panel->funcs;
|
||||
ofnode panel_node = panel_state->node;
|
||||
int ret;
|
||||
|
||||
if (ofnode_valid(panel) && !display_get_timing_from_dts(panel_state, mode)) {
|
||||
if (ofnode_valid(panel_node) && !display_get_timing_from_dts(panel_state, mode)) {
|
||||
printf("Using display timing dts\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
m = rockchip_get_display_mode_from_panel(state);
|
||||
if (m) {
|
||||
printf("Using display timing from compatible panel driver\n");
|
||||
if (panel->data) {
|
||||
m = (const struct drm_display_mode *)panel->data;
|
||||
memcpy(mode, m, sizeof(*m));
|
||||
printf("Using display timing from compatible panel driver\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
rockchip_panel_prepare(state);
|
||||
|
||||
if (conn_funcs->get_edid && !conn_funcs->get_edid(state)) {
|
||||
int panel_bits_per_colourp;
|
||||
|
||||
/* In order to read EDID, the panel needs to be powered on */
|
||||
if (panel_funcs->prepare) {
|
||||
ret = panel_funcs->prepare(state);
|
||||
if (ret) {
|
||||
printf("failed to prepare panel\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (!edid_get_drm_mode((void *)&conn_state->edid,
|
||||
sizeof(conn_state->edid), mode,
|
||||
&panel_bits_per_colourp)) {
|
||||
printf("Using display timing from edid\n");
|
||||
edid_print_info((void *)&conn_state->edid);
|
||||
goto done;
|
||||
} else {
|
||||
if (panel_funcs->unprepare)
|
||||
panel_funcs->unprepare(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -547,6 +562,9 @@ static int display_enable(struct display_state *state)
|
|||
struct crtc_state *crtc_state = &state->crtc_state;
|
||||
const struct rockchip_crtc *crtc = crtc_state->crtc;
|
||||
const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs;
|
||||
struct panel_state *panel_state = &state->panel_state;
|
||||
const struct rockchip_panel *panel = panel_state->panel;
|
||||
const struct rockchip_panel_funcs *panel_funcs = panel->funcs;
|
||||
int ret = 0;
|
||||
|
||||
display_init(state);
|
||||
|
|
@ -569,12 +587,18 @@ static int display_enable(struct display_state *state)
|
|||
goto unprepare_crtc;
|
||||
}
|
||||
|
||||
rockchip_panel_prepare(state);
|
||||
if (panel_funcs->prepare) {
|
||||
ret = panel_funcs->prepare(state);
|
||||
if (ret) {
|
||||
printf("failed to prepare panel\n");
|
||||
goto unprepare_conn;
|
||||
}
|
||||
}
|
||||
|
||||
if (crtc_funcs->enable) {
|
||||
ret = crtc_funcs->enable(state);
|
||||
if (ret)
|
||||
goto unprepare_conn;
|
||||
goto unprepare_panel;
|
||||
}
|
||||
|
||||
if (conn_funcs->enable) {
|
||||
|
|
@ -583,20 +607,33 @@ static int display_enable(struct display_state *state)
|
|||
goto disable_crtc;
|
||||
}
|
||||
|
||||
rockchip_panel_enable(state);
|
||||
if (panel_funcs->enable) {
|
||||
ret = panel_funcs->enable(state);
|
||||
if (ret) {
|
||||
printf("failed to enable panel\n");
|
||||
goto disable_conn;
|
||||
}
|
||||
}
|
||||
|
||||
state->is_enable = true;
|
||||
|
||||
return 0;
|
||||
unprepare_crtc:
|
||||
if (crtc_funcs->unprepare)
|
||||
crtc_funcs->unprepare(state);
|
||||
unprepare_conn:
|
||||
|
||||
disable_conn:
|
||||
if (conn_funcs->unprepare)
|
||||
conn_funcs->unprepare(state);
|
||||
disable_crtc:
|
||||
if (crtc_funcs->disable)
|
||||
crtc_funcs->disable(state);
|
||||
unprepare_crtc:
|
||||
if (crtc_funcs->unprepare)
|
||||
crtc_funcs->unprepare(state);
|
||||
unprepare_panel:
|
||||
if (panel_funcs->unprepare)
|
||||
panel_funcs->unprepare(state);
|
||||
unprepare_conn:
|
||||
if (conn_funcs->unprepare)
|
||||
conn_funcs->unprepare(state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -608,6 +645,9 @@ static int display_disable(struct display_state *state)
|
|||
struct crtc_state *crtc_state = &state->crtc_state;
|
||||
const struct rockchip_crtc *crtc = crtc_state->crtc;
|
||||
const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs;
|
||||
struct panel_state *panel_state = &state->panel_state;
|
||||
const struct rockchip_panel *panel = panel_state->panel;
|
||||
const struct rockchip_panel_funcs *panel_funcs = panel->funcs;
|
||||
|
||||
if (!state->is_init)
|
||||
return 0;
|
||||
|
|
@ -615,7 +655,8 @@ static int display_disable(struct display_state *state)
|
|||
if (!state->is_enable)
|
||||
return 0;
|
||||
|
||||
rockchip_panel_disable(state);
|
||||
if (panel_funcs->disable)
|
||||
panel_funcs->disable(state);
|
||||
|
||||
if (crtc_funcs->disable)
|
||||
crtc_funcs->disable(state);
|
||||
|
|
@ -623,7 +664,8 @@ static int display_disable(struct display_state *state)
|
|||
if (conn_funcs->disable)
|
||||
conn_funcs->disable(state);
|
||||
|
||||
rockchip_panel_unprepare(state);
|
||||
if (panel_funcs->unprepare)
|
||||
panel_funcs->unprepare(state);
|
||||
|
||||
if (conn_funcs->unprepare)
|
||||
conn_funcs->unprepare(state);
|
||||
|
|
|
|||
|
|
@ -1,411 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <common.h>
|
||||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/media-bus-format.h>
|
||||
#include <dm/uclass.h>
|
||||
#include <dm/uclass-id.h>
|
||||
#include <video.h>
|
||||
#include <dm/device.h>
|
||||
#include <dm/uclass-internal.h>
|
||||
#include <backlight.h>
|
||||
#include <power/regulator.h>
|
||||
#include <asm/gpio.h>
|
||||
|
||||
#include "rockchip_display.h"
|
||||
#include "rockchip_crtc.h"
|
||||
#include "rockchip_connector.h"
|
||||
#include "rockchip_panel.h"
|
||||
#include "rockchip_mipi_dsi.h"
|
||||
|
||||
#define msleep(a) udelay(a * 1000)
|
||||
|
||||
struct dsi_ctrl_hdr {
|
||||
u8 dtype; /* data type */
|
||||
u8 wait; /* ms */
|
||||
u8 dlen; /* payload len */
|
||||
} __packed;
|
||||
|
||||
struct dsi_cmd_desc {
|
||||
struct dsi_ctrl_hdr dchdr;
|
||||
u8 *payload;
|
||||
};
|
||||
|
||||
struct dsi_panel_cmds {
|
||||
u8 *buf;
|
||||
int blen;
|
||||
struct dsi_cmd_desc *cmds;
|
||||
int cmd_cnt;
|
||||
};
|
||||
|
||||
struct rockchip_dsi_panel {
|
||||
struct udevice *dev;
|
||||
const void *blob;
|
||||
ofnode node;
|
||||
|
||||
int bus_format;
|
||||
|
||||
struct udevice *power_supply;
|
||||
bool power_invert;
|
||||
struct udevice *backlight;
|
||||
struct gpio_desc enable;
|
||||
struct gpio_desc reset;
|
||||
|
||||
unsigned int delay_reset;
|
||||
unsigned int delay_prepare;
|
||||
unsigned int delay_unprepare;
|
||||
unsigned int delay_enable;
|
||||
unsigned int delay_disable;
|
||||
unsigned int delay_init;
|
||||
|
||||
struct dsi_panel_cmds *on_cmds;
|
||||
struct dsi_panel_cmds *off_cmds;
|
||||
};
|
||||
|
||||
static int rockchip_dsi_panel_parse_cmds(ofnode node,
|
||||
const u8 *data, int blen,
|
||||
struct dsi_panel_cmds *pcmds)
|
||||
{
|
||||
int len;
|
||||
u8 *buf, *bp;
|
||||
struct dsi_ctrl_hdr *dchdr;
|
||||
int i, cnt;
|
||||
|
||||
if (!pcmds)
|
||||
return -EINVAL;
|
||||
|
||||
buf = malloc(sizeof(char) * blen);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(buf, data, blen);
|
||||
|
||||
/* scan dcs commands */
|
||||
bp = buf;
|
||||
len = blen;
|
||||
cnt = 0;
|
||||
while (len > sizeof(*dchdr)) {
|
||||
dchdr = (struct dsi_ctrl_hdr *)bp;
|
||||
if (dchdr->dlen > len) {
|
||||
printf("%s: dtsi cmd=%x error, len=%d",
|
||||
__func__, dchdr->dtype, dchdr->dlen);
|
||||
free(buf);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
bp += sizeof(*dchdr);
|
||||
len -= sizeof(*dchdr);
|
||||
bp += dchdr->dlen;
|
||||
len -= dchdr->dlen;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
if (len != 0) {
|
||||
printf("%s: dcs_cmd=%x len=%d error!", __func__, buf[0], blen);
|
||||
free(buf);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pcmds->cmds = malloc(cnt * sizeof(struct dsi_cmd_desc));
|
||||
if (!pcmds->cmds) {
|
||||
free(buf);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pcmds->cmd_cnt = cnt;
|
||||
pcmds->buf = buf;
|
||||
pcmds->blen = blen;
|
||||
|
||||
bp = buf;
|
||||
len = blen;
|
||||
for (i = 0; i < cnt; i++) {
|
||||
dchdr = (struct dsi_ctrl_hdr *)bp;
|
||||
len -= sizeof(*dchdr);
|
||||
bp += sizeof(*dchdr);
|
||||
pcmds->cmds[i].dchdr = *dchdr;
|
||||
pcmds->cmds[i].payload = bp;
|
||||
bp += dchdr->dlen;
|
||||
len -= dchdr->dlen;
|
||||
}
|
||||
|
||||
debug("%s: total_len=%d, cmd_cnt=%d\n",
|
||||
__func__, pcmds->blen, pcmds->cmd_cnt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_dsi_panel_send_cmds(struct display_state *state,
|
||||
struct dsi_panel_cmds *cmds)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
if (!cmds)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < cmds->cmd_cnt; i++) {
|
||||
switch (cmds->cmds[i].dchdr.dtype) {
|
||||
case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
|
||||
case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
|
||||
case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
|
||||
case MIPI_DSI_GENERIC_LONG_WRITE:
|
||||
ret = mipi_dsi_generic_write(state, cmds->cmds[i].payload,
|
||||
cmds->cmds[i].dchdr.dlen);
|
||||
break;
|
||||
case MIPI_DSI_DCS_SHORT_WRITE:
|
||||
case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
|
||||
case MIPI_DSI_DCS_LONG_WRITE:
|
||||
ret = mipi_dsi_dcs_write(state, cmds->cmds[i].payload,
|
||||
cmds->cmds[i].dchdr.dlen);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
printf("failed to write cmd%d: %d\n", i, ret);
|
||||
|
||||
if (cmds->cmds[i].dchdr.wait)
|
||||
msleep(cmds->cmds[i].dchdr.wait);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_dsi_panel_prepare(struct display_state *state)
|
||||
{
|
||||
struct panel_state *panel_state = &state->panel_state;
|
||||
struct rockchip_dsi_panel *panel = panel_state->private;
|
||||
int ret;
|
||||
|
||||
if (panel->power_supply) {
|
||||
ret = regulator_set_enable(panel->power_supply,
|
||||
panel->power_invert);
|
||||
if (ret)
|
||||
printf("%s: failed to enable power_supply",
|
||||
__func__);
|
||||
}
|
||||
|
||||
dm_gpio_set_value(&panel->enable, 1);
|
||||
msleep(panel->delay_prepare);
|
||||
|
||||
dm_gpio_set_value(&panel->reset, 1);
|
||||
msleep(panel->delay_reset);
|
||||
dm_gpio_set_value(&panel->reset, 0);
|
||||
|
||||
msleep(panel->delay_init);
|
||||
|
||||
if (panel->on_cmds) {
|
||||
ret = rockchip_dsi_panel_send_cmds(state, panel->on_cmds);
|
||||
if (ret)
|
||||
printf("failed to send on cmds: %d\n", ret);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_dsi_panel_unprepare(struct display_state *state)
|
||||
{
|
||||
struct panel_state *panel_state = &state->panel_state;
|
||||
struct rockchip_dsi_panel *panel = panel_state->private;
|
||||
int ret;
|
||||
|
||||
if (panel->off_cmds) {
|
||||
ret = rockchip_dsi_panel_send_cmds(state, panel->off_cmds);
|
||||
if (ret)
|
||||
printf("failed to send on cmds: %d\n", ret);
|
||||
}
|
||||
|
||||
dm_gpio_set_value(&panel->reset, 0);
|
||||
|
||||
mdelay(panel->delay_unprepare);
|
||||
|
||||
dm_gpio_set_value(&panel->enable, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_dsi_panel_enable(struct display_state *state)
|
||||
{
|
||||
struct panel_state *panel_state = &state->panel_state;
|
||||
struct rockchip_dsi_panel *panel = panel_state->private;
|
||||
int ret;
|
||||
|
||||
if (panel->backlight) {
|
||||
ret = backlight_enable(panel->backlight);
|
||||
mdelay(panel->delay_enable);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_dsi_panel_disable(struct display_state *state)
|
||||
{
|
||||
struct panel_state *panel_state = &state->panel_state;
|
||||
struct rockchip_dsi_panel *panel = panel_state->private;
|
||||
int ret;
|
||||
|
||||
if (panel->backlight) {
|
||||
ret = backlight_disable(panel->backlight);
|
||||
mdelay(panel->delay_disable);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_dsi_panel_parse_dt(ofnode node, struct rockchip_dsi_panel *panel)
|
||||
{
|
||||
const void *data;
|
||||
int len = 0;
|
||||
int ret = 0;
|
||||
|
||||
panel->delay_prepare = ofnode_read_u32_default(node, "prepare-delay-ms", 0);
|
||||
panel->delay_unprepare = ofnode_read_u32_default(node, "unprepare-delay-ms", 0);
|
||||
panel->delay_enable = ofnode_read_u32_default(node, "enable-delay-ms", 0);
|
||||
panel->delay_disable = ofnode_read_u32_default(node, "disable-delay-ms", 0);
|
||||
panel->delay_init = ofnode_read_u32_default(node, "init-delay-ms", 0);
|
||||
panel->delay_reset = ofnode_read_u32_default(node, "reset-delay-ms", 0);
|
||||
panel->bus_format = ofnode_read_u32_default(node, "bus-format", MEDIA_BUS_FMT_RBG888_1X24);
|
||||
|
||||
data = ofnode_get_property(node, "panel-init-sequence", &len);
|
||||
if (data) {
|
||||
panel->on_cmds = malloc(sizeof(*panel->on_cmds));
|
||||
if (!panel->on_cmds)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = rockchip_dsi_panel_parse_cmds(node, data, len,
|
||||
panel->on_cmds);
|
||||
if (ret) {
|
||||
printf("failed to parse panel init sequence\n");
|
||||
goto free_on_cmds;
|
||||
}
|
||||
}
|
||||
|
||||
data = ofnode_get_property(node, "panel-exit-sequence", &len);
|
||||
if (data) {
|
||||
panel->off_cmds = malloc(sizeof(*panel->off_cmds));
|
||||
if (!panel->off_cmds) {
|
||||
ret = -ENOMEM;
|
||||
goto free_on_cmds;
|
||||
}
|
||||
|
||||
ret = rockchip_dsi_panel_parse_cmds(node, data, len,
|
||||
panel->off_cmds);
|
||||
if (ret) {
|
||||
printf("failed to parse panel exit sequence\n");
|
||||
goto free_cmds;
|
||||
}
|
||||
}
|
||||
|
||||
ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, panel->dev,
|
||||
"backlight", &panel->backlight);
|
||||
if (ret) {
|
||||
printf("%s: Cannot get backlight: ret=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = gpio_request_by_name(panel->dev, "enable-gpios", 0,
|
||||
&panel->enable, GPIOD_IS_OUT);
|
||||
if (ret && ret != -ENOENT) {
|
||||
printf("%s: Warning: cannot get enable GPIO: ret=%d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = gpio_request_by_name(panel->dev, "reset-gpios", 0,
|
||||
&panel->reset, GPIOD_IS_OUT);
|
||||
if (ret && ret != -ENOENT) {
|
||||
printf("%s: Warning: cannot get reset GPIO: ret=%d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, panel->dev,
|
||||
"power-supply",
|
||||
&panel->power_supply);
|
||||
if (ret && ret != -ENOENT) {
|
||||
printf("%s: Cannot get power supply: ret=%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
panel->power_invert = !!ofnode_read_u32_default(node, "power_invert", 0);
|
||||
|
||||
/* keep panel blank on init. */
|
||||
dm_gpio_set_value(&panel->enable, 0);
|
||||
dm_gpio_set_value(&panel->reset, 0);
|
||||
|
||||
return 0;
|
||||
|
||||
free_cmds:
|
||||
free(panel->off_cmds);
|
||||
free_on_cmds:
|
||||
free(panel->on_cmds);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rockchip_dsi_panel_init(struct display_state *state)
|
||||
{
|
||||
const void *blob = state->blob;
|
||||
struct connector_state *conn_state = &state->conn_state;
|
||||
struct panel_state *panel_state = &state->panel_state;
|
||||
ofnode node = panel_state->node;
|
||||
struct rockchip_dsi_panel *panel;
|
||||
int ret;
|
||||
|
||||
panel = malloc(sizeof(*panel));
|
||||
if (!panel)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(panel, 0, sizeof(*panel));
|
||||
|
||||
panel->blob = blob;
|
||||
panel->node = node;
|
||||
panel->dev = panel_state->dev;
|
||||
panel_state->private = panel;
|
||||
|
||||
ret = rockchip_dsi_panel_parse_dt(node, panel);
|
||||
if (ret) {
|
||||
printf("%s: failed to parse DT\n", __func__);
|
||||
free(panel);
|
||||
return ret;
|
||||
}
|
||||
|
||||
conn_state->bus_format = panel->bus_format;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rockchip_dsi_panel_deinit(struct display_state *state)
|
||||
{
|
||||
struct panel_state *panel_state = &state->panel_state;
|
||||
struct rockchip_dsi_panel *panel = panel_state->private;
|
||||
|
||||
if (panel->on_cmds) {
|
||||
free(panel->on_cmds->buf);
|
||||
free(panel->on_cmds->cmds);
|
||||
}
|
||||
|
||||
if (panel->off_cmds) {
|
||||
free(panel->off_cmds->buf);
|
||||
free(panel->off_cmds->cmds);
|
||||
}
|
||||
|
||||
free(panel);
|
||||
}
|
||||
|
||||
const struct rockchip_panel_funcs rockchip_dsi_panel_funcs = {
|
||||
.init = rockchip_dsi_panel_init,
|
||||
.deinit = rockchip_dsi_panel_deinit,
|
||||
.prepare = rockchip_dsi_panel_prepare,
|
||||
.unprepare = rockchip_dsi_panel_unprepare,
|
||||
.enable = rockchip_dsi_panel_enable,
|
||||
.disable = rockchip_dsi_panel_disable,
|
||||
};
|
||||
|
|
@ -4,18 +4,372 @@
|
|||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <asm/unaligned.h>
|
||||
#include <config.h>
|
||||
#include <common.h>
|
||||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#include <video.h>
|
||||
#include <backlight.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <dm/device.h>
|
||||
#include <dm/read.h>
|
||||
#include <dm/uclass.h>
|
||||
#include <dm/uclass-id.h>
|
||||
#include <linux/media-bus-format.h>
|
||||
#include <power/regulator.h>
|
||||
|
||||
#include "rockchip_display.h"
|
||||
#include "rockchip_crtc.h"
|
||||
#include "rockchip_connector.h"
|
||||
#include "rockchip_mipi_dsi.h"
|
||||
#include "rockchip_panel.h"
|
||||
|
||||
#ifdef CONFIG_DRM_ROCKCHIP_PANEL
|
||||
struct rockchip_cmd_header {
|
||||
u8 data_type;
|
||||
u8 delay_ms;
|
||||
u8 payload_length;
|
||||
} __packed;
|
||||
|
||||
struct rockchip_cmd_desc {
|
||||
struct rockchip_cmd_header header;
|
||||
const u8 *payload;
|
||||
};
|
||||
|
||||
struct rockchip_panel_cmds {
|
||||
struct rockchip_cmd_desc *cmds;
|
||||
int cmd_cnt;
|
||||
};
|
||||
|
||||
struct rockchip_panel_plat {
|
||||
bool power_invert;
|
||||
u32 bus_format;
|
||||
|
||||
struct {
|
||||
unsigned int prepare;
|
||||
unsigned int unprepare;
|
||||
unsigned int enable;
|
||||
unsigned int disable;
|
||||
unsigned int reset;
|
||||
unsigned int init;
|
||||
} delay;
|
||||
|
||||
struct rockchip_panel_cmds *on_cmds;
|
||||
struct rockchip_panel_cmds *off_cmds;
|
||||
};
|
||||
|
||||
struct rockchip_panel_priv {
|
||||
bool prepared;
|
||||
bool enabled;
|
||||
struct udevice *power_supply;
|
||||
struct udevice *backlight;
|
||||
struct gpio_desc enable_gpio;
|
||||
struct gpio_desc reset_gpio;
|
||||
};
|
||||
|
||||
static int rockchip_panel_parse_cmds(const u8 *data, int length,
|
||||
struct rockchip_panel_cmds *pcmds)
|
||||
{
|
||||
int len;
|
||||
const u8 *buf;
|
||||
const struct rockchip_cmd_header *header;
|
||||
int i, cnt = 0;
|
||||
|
||||
/* scan commands */
|
||||
cnt = 0;
|
||||
buf = data;
|
||||
len = length;
|
||||
while (len > sizeof(*header)) {
|
||||
header = (const struct rockchip_cmd_header *)buf;
|
||||
buf += sizeof(*header) + header->payload_length;
|
||||
len -= sizeof(*header) + header->payload_length;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
pcmds->cmds = calloc(cnt, sizeof(struct rockchip_cmd_desc));
|
||||
if (!pcmds->cmds)
|
||||
return -ENOMEM;
|
||||
|
||||
pcmds->cmd_cnt = cnt;
|
||||
|
||||
buf = data;
|
||||
len = length;
|
||||
for (i = 0; i < cnt; i++) {
|
||||
struct rockchip_cmd_desc *desc = &pcmds->cmds[i];
|
||||
|
||||
header = (const struct rockchip_cmd_header *)buf;
|
||||
length -= sizeof(*header);
|
||||
buf += sizeof(*header);
|
||||
desc->header.data_type = header->data_type;
|
||||
desc->header.delay_ms = header->delay_ms;
|
||||
desc->header.payload_length = header->payload_length;
|
||||
desc->payload = buf;
|
||||
buf += header->payload_length;
|
||||
length -= header->payload_length;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_panel_send_cmds(struct display_state *state,
|
||||
struct rockchip_panel_cmds *cmds)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
if (!cmds)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < cmds->cmd_cnt; i++) {
|
||||
struct rockchip_cmd_desc *desc = &cmds->cmds[i];
|
||||
|
||||
switch (desc->header.data_type) {
|
||||
case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
|
||||
case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
|
||||
case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
|
||||
case MIPI_DSI_GENERIC_LONG_WRITE:
|
||||
ret = mipi_dsi_generic_write(state, desc->payload,
|
||||
desc->header.payload_length);
|
||||
break;
|
||||
case MIPI_DSI_DCS_SHORT_WRITE:
|
||||
case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
|
||||
case MIPI_DSI_DCS_LONG_WRITE:
|
||||
ret = mipi_dsi_dcs_write(state, desc->payload,
|
||||
desc->header.payload_length);
|
||||
break;
|
||||
default:
|
||||
printf("unsupport command data type: %d\n",
|
||||
desc->header.data_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
printf("failed to write cmd%d: %d\n", i, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (desc->header.delay_ms)
|
||||
mdelay(desc->header.delay_ms);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_panel_prepare(struct display_state *state)
|
||||
{
|
||||
struct panel_state *panel_state = &state->panel_state;
|
||||
struct rockchip_panel_plat *plat = dev_get_platdata(panel_state->dev);
|
||||
struct rockchip_panel_priv *priv = dev_get_priv(panel_state->dev);
|
||||
int ret;
|
||||
|
||||
if (priv->prepared)
|
||||
return 0;
|
||||
|
||||
if (priv->power_supply) {
|
||||
ret = regulator_set_enable(priv->power_supply,
|
||||
!plat->power_invert);
|
||||
if (ret) {
|
||||
printf("%s: failed to enable power supply", __func__);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
dm_gpio_set_value(&priv->enable_gpio, 1);
|
||||
mdelay(plat->delay.prepare);
|
||||
|
||||
dm_gpio_set_value(&priv->reset_gpio, 1);
|
||||
mdelay(plat->delay.reset);
|
||||
dm_gpio_set_value(&priv->reset_gpio, 0);
|
||||
|
||||
mdelay(plat->delay.init);
|
||||
|
||||
if (plat->on_cmds) {
|
||||
ret = rockchip_panel_send_cmds(state, plat->on_cmds);
|
||||
if (ret)
|
||||
printf("failed to send on cmds: %d\n", ret);
|
||||
}
|
||||
|
||||
priv->prepared = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rockchip_panel_unprepare(struct display_state *state)
|
||||
{
|
||||
struct panel_state *panel_state = &state->panel_state;
|
||||
struct rockchip_panel_plat *plat = dev_get_platdata(panel_state->dev);
|
||||
struct rockchip_panel_priv *priv = dev_get_priv(panel_state->dev);
|
||||
int ret;
|
||||
|
||||
if (!priv->prepared)
|
||||
return;
|
||||
|
||||
if (plat->off_cmds) {
|
||||
ret = rockchip_panel_send_cmds(state, plat->off_cmds);
|
||||
if (ret)
|
||||
printf("failed to send off cmds: %d\n", ret);
|
||||
}
|
||||
|
||||
dm_gpio_set_value(&priv->reset_gpio, 1);
|
||||
dm_gpio_set_value(&priv->enable_gpio, 0);
|
||||
|
||||
if (priv->power_supply) {
|
||||
ret = regulator_set_enable(priv->power_supply,
|
||||
plat->power_invert);
|
||||
if (ret)
|
||||
printf("%s: failed to disable power supply", __func__);
|
||||
}
|
||||
|
||||
mdelay(plat->delay.unprepare);
|
||||
|
||||
priv->prepared = false;
|
||||
}
|
||||
|
||||
static int rockchip_panel_enable(struct display_state *state)
|
||||
{
|
||||
struct panel_state *panel_state = &state->panel_state;
|
||||
struct rockchip_panel_plat *plat = dev_get_platdata(panel_state->dev);
|
||||
struct rockchip_panel_priv *priv = dev_get_priv(panel_state->dev);
|
||||
|
||||
if (priv->enabled)
|
||||
return 0;
|
||||
|
||||
mdelay(plat->delay.enable);
|
||||
|
||||
if (priv->backlight)
|
||||
backlight_enable(priv->backlight);
|
||||
|
||||
priv->enabled = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rockchip_panel_disable(struct display_state *state)
|
||||
{
|
||||
struct panel_state *panel_state = &state->panel_state;
|
||||
struct rockchip_panel_plat *plat = dev_get_platdata(panel_state->dev);
|
||||
struct rockchip_panel_priv *priv = dev_get_priv(panel_state->dev);
|
||||
|
||||
if (!priv->enabled)
|
||||
return;
|
||||
|
||||
if (priv->backlight)
|
||||
backlight_disable(priv->backlight);
|
||||
|
||||
mdelay(plat->delay.disable);
|
||||
|
||||
priv->enabled = false;
|
||||
}
|
||||
|
||||
static int rockchip_panel_init(struct display_state *state)
|
||||
{
|
||||
struct connector_state *conn_state = &state->conn_state;
|
||||
struct panel_state *panel_state = &state->panel_state;
|
||||
struct rockchip_panel_plat *plat = dev_get_platdata(panel_state->dev);
|
||||
|
||||
conn_state->bus_format = plat->bus_format;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct rockchip_panel_funcs rockchip_panel_funcs = {
|
||||
.init = rockchip_panel_init,
|
||||
.prepare = rockchip_panel_prepare,
|
||||
.unprepare = rockchip_panel_unprepare,
|
||||
.enable = rockchip_panel_enable,
|
||||
.disable = rockchip_panel_disable,
|
||||
};
|
||||
|
||||
static int rockchip_panel_ofdata_to_platdata(struct udevice *dev)
|
||||
{
|
||||
struct rockchip_panel_plat *plat = dev_get_platdata(dev);
|
||||
const void *data;
|
||||
int len = 0;
|
||||
int ret;
|
||||
|
||||
plat->power_invert = dev_read_bool(dev, "power-invert");
|
||||
|
||||
plat->delay.prepare = dev_read_u32_default(dev, "prepare-delay-ms", 0);
|
||||
plat->delay.unprepare = dev_read_u32_default(dev, "unprepare-delay-ms", 0);
|
||||
plat->delay.enable = dev_read_u32_default(dev, "enable-delay-ms", 0);
|
||||
plat->delay.disable = dev_read_u32_default(dev, "disable-delay-ms", 0);
|
||||
plat->delay.init = dev_read_u32_default(dev, "init-delay-ms", 0);
|
||||
plat->delay.reset = dev_read_u32_default(dev, "reset-delay-ms", 0);
|
||||
|
||||
plat->bus_format = dev_read_u32_default(dev, "bus-format",
|
||||
MEDIA_BUS_FMT_RBG888_1X24);
|
||||
|
||||
data = dev_read_prop(dev, "panel-init-sequence", &len);
|
||||
if (data) {
|
||||
plat->on_cmds = calloc(1, sizeof(*plat->on_cmds));
|
||||
if (!plat->on_cmds)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = rockchip_panel_parse_cmds(data, len, plat->on_cmds);
|
||||
if (ret) {
|
||||
printf("failed to parse panel init sequence\n");
|
||||
goto free_on_cmds;
|
||||
}
|
||||
}
|
||||
|
||||
data = dev_read_prop(dev, "panel-exit-sequence", &len);
|
||||
if (data) {
|
||||
plat->off_cmds = calloc(1, sizeof(*plat->off_cmds));
|
||||
if (!plat->off_cmds) {
|
||||
ret = -ENOMEM;
|
||||
goto free_on_cmds;
|
||||
}
|
||||
|
||||
ret = rockchip_panel_parse_cmds(data, len, plat->off_cmds);
|
||||
if (ret) {
|
||||
printf("failed to parse panel exit sequence\n");
|
||||
goto free_cmds;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
free_cmds:
|
||||
free(plat->off_cmds);
|
||||
free_on_cmds:
|
||||
free(plat->on_cmds);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rockchip_panel_probe(struct udevice *dev)
|
||||
{
|
||||
struct rockchip_panel_priv *priv = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
ret = gpio_request_by_name(dev, "enable-gpios", 0,
|
||||
&priv->enable_gpio, GPIOD_IS_OUT);
|
||||
if (ret && ret != -ENOENT) {
|
||||
printf("%s: Cannot get enable GPIO: %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = gpio_request_by_name(dev, "reset-gpios", 0,
|
||||
&priv->reset_gpio, GPIOD_IS_OUT);
|
||||
if (ret && ret != -ENOENT) {
|
||||
printf("%s: Cannot get reset GPIO: %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
|
||||
"backlight", &priv->backlight);
|
||||
if (ret && ret != -ENOENT) {
|
||||
printf("%s: Cannot get backlight: %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev,
|
||||
"power-supply", &priv->power_supply);
|
||||
if (ret && ret != -ENOENT) {
|
||||
printf("%s: Cannot get power supply: %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_display_mode auo_b125han03_mode = {
|
||||
.clock = 146900,
|
||||
.hdisplay = 1920,
|
||||
|
|
@ -30,6 +384,11 @@ static const struct drm_display_mode auo_b125han03_mode = {
|
|||
.flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
|
||||
};
|
||||
|
||||
static const struct rockchip_panel auo_b125han03_data = {
|
||||
.funcs = &rockchip_panel_funcs,
|
||||
.data = &auo_b125han03_mode,
|
||||
};
|
||||
|
||||
static const struct drm_display_mode lg_lp079qx1_sp0v_mode = {
|
||||
.clock = 200000,
|
||||
.hdisplay = 1536,
|
||||
|
|
@ -44,153 +403,38 @@ static const struct drm_display_mode lg_lp079qx1_sp0v_mode = {
|
|||
.flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
|
||||
};
|
||||
|
||||
static const struct rockchip_panel simple_panel_data = {
|
||||
.funcs = &panel_simple_funcs,
|
||||
};
|
||||
|
||||
static const struct rockchip_panel lg_lp079qx1_sp0v_data = {
|
||||
.funcs = &panel_simple_funcs,
|
||||
.funcs = &rockchip_panel_funcs,
|
||||
.data = &lg_lp079qx1_sp0v_mode,
|
||||
};
|
||||
|
||||
static const struct rockchip_panel auo_b125han03_data = {
|
||||
.funcs = &panel_simple_funcs,
|
||||
.data = &auo_b125han03_mode,
|
||||
static const struct rockchip_panel rockchip_panel_data = {
|
||||
.funcs = &rockchip_panel_funcs,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DRM_ROCKCHIP_DSI_PANEL
|
||||
static const struct rockchip_panel simple_panel_dsi_data = {
|
||||
.funcs = &rockchip_dsi_panel_funcs,
|
||||
};
|
||||
#endif
|
||||
|
||||
static const struct udevice_id rockchip_panel_ids[] = {
|
||||
#ifdef CONFIG_DRM_ROCKCHIP_PANEL
|
||||
{
|
||||
.compatible = "simple-panel",
|
||||
.data = (ulong)&simple_panel_data,
|
||||
.compatible = "auo,b125han03",
|
||||
.data = (ulong)&auo_b125han03_data,
|
||||
}, {
|
||||
.compatible = "lg,lp079qx1-sp0v",
|
||||
.data = (ulong)&lg_lp079qx1_sp0v_data,
|
||||
}, {
|
||||
.compatible = "auo,b125han03",
|
||||
.data = (ulong)&auo_b125han03_data,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_DRM_ROCKCHIP_DSI_PANEL
|
||||
{
|
||||
.compatible = "simple-panel",
|
||||
.data = (ulong)&rockchip_panel_data,
|
||||
}, {
|
||||
.compatible = "simple-panel-dsi",
|
||||
.data = (ulong)&simple_panel_dsi_data,
|
||||
.data = (ulong)&rockchip_panel_data,
|
||||
},
|
||||
#endif
|
||||
{}
|
||||
};
|
||||
|
||||
static int rockchip_panel_probe(struct udevice *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_panel_bind(struct udevice *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_DRIVER(rockchip_panel) = {
|
||||
.name = "rockchip_panel",
|
||||
.id = UCLASS_PANEL,
|
||||
.of_match = rockchip_panel_ids,
|
||||
.bind = rockchip_panel_bind,
|
||||
.ofdata_to_platdata = rockchip_panel_ofdata_to_platdata,
|
||||
.probe = rockchip_panel_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct rockchip_panel_priv),
|
||||
.platdata_auto_alloc_size = sizeof(struct rockchip_panel_plat),
|
||||
};
|
||||
|
||||
const struct drm_display_mode *
|
||||
rockchip_get_display_mode_from_panel(struct display_state *state)
|
||||
{
|
||||
struct panel_state *panel_state = &state->panel_state;
|
||||
const struct rockchip_panel *panel = panel_state->panel;
|
||||
|
||||
if (!panel || !panel->data)
|
||||
return NULL;
|
||||
|
||||
return (const struct drm_display_mode *)panel->data;
|
||||
}
|
||||
|
||||
int rockchip_panel_init(struct display_state *state)
|
||||
{
|
||||
struct panel_state *panel_state = &state->panel_state;
|
||||
const struct rockchip_panel *panel = panel_state->panel;
|
||||
|
||||
if (!panel || !panel->funcs || !panel->funcs->init) {
|
||||
printf("%s: failed to find panel init funcs\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return panel->funcs->init(state);
|
||||
}
|
||||
|
||||
void rockchip_panel_deinit(struct display_state *state)
|
||||
{
|
||||
struct panel_state *panel_state = &state->panel_state;
|
||||
const struct rockchip_panel *panel = panel_state->panel;
|
||||
|
||||
if (!panel || !panel->funcs || !panel->funcs->deinit) {
|
||||
printf("%s: failed to find panel deinit funcs\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
panel->funcs->deinit(state);
|
||||
}
|
||||
|
||||
int rockchip_panel_prepare(struct display_state *state)
|
||||
{
|
||||
struct panel_state *panel_state = &state->panel_state;
|
||||
const struct rockchip_panel *panel = panel_state->panel;
|
||||
|
||||
if (!panel || !panel->funcs || !panel->funcs->prepare) {
|
||||
printf("%s: failed to find panel prepare funcs\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return panel->funcs->prepare(state);
|
||||
}
|
||||
|
||||
int rockchip_panel_unprepare(struct display_state *state)
|
||||
{
|
||||
struct panel_state *panel_state = &state->panel_state;
|
||||
const struct rockchip_panel *panel = panel_state->panel;
|
||||
|
||||
if (!panel || !panel->funcs || !panel->funcs->unprepare) {
|
||||
printf("%s: failed to find panel unprepare funcs\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return panel->funcs->unprepare(state);
|
||||
}
|
||||
|
||||
int rockchip_panel_enable(struct display_state *state)
|
||||
{
|
||||
struct panel_state *panel_state = &state->panel_state;
|
||||
const struct rockchip_panel *panel = panel_state->panel;
|
||||
|
||||
if (!panel || !panel->funcs || !panel->funcs->enable) {
|
||||
printf("%s: failed to find panel prepare funcs\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return panel->funcs->enable(state);
|
||||
}
|
||||
|
||||
int rockchip_panel_disable(struct display_state *state)
|
||||
{
|
||||
struct panel_state *panel_state = &state->panel_state;
|
||||
const struct rockchip_panel *panel = panel_state->panel;
|
||||
|
||||
if (!panel || !panel->funcs || !panel->funcs->disable) {
|
||||
printf("%s: failed to find panel disable funcs\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return panel->funcs->disable(state);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ struct rockchip_panel_funcs {
|
|||
int (*init)(struct display_state *state);
|
||||
void (*deinit)(struct display_state *state);
|
||||
int (*prepare)(struct display_state *state);
|
||||
int (*unprepare)(struct display_state *state);
|
||||
void (*unprepare)(struct display_state *state);
|
||||
int (*enable)(struct display_state *state);
|
||||
int (*disable)(struct display_state *state);
|
||||
void (*disable)(struct display_state *state);
|
||||
};
|
||||
|
||||
struct rockchip_panel {
|
||||
|
|
@ -21,20 +21,4 @@ struct rockchip_panel {
|
|||
const void *data;
|
||||
};
|
||||
|
||||
const struct rockchip_panel *rockchip_get_panel(const void *blob, int node);
|
||||
const struct drm_display_mode *
|
||||
rockchip_get_display_mode_from_panel(struct display_state *state);
|
||||
int rockchip_panel_init(struct display_state *state);
|
||||
void rockchip_panel_deinit(struct display_state *state);
|
||||
int rockchip_panel_enable(struct display_state *state);
|
||||
int rockchip_panel_disable(struct display_state *state);
|
||||
int rockchip_panel_prepare(struct display_state *state);
|
||||
int rockchip_panel_unprepare(struct display_state *state);
|
||||
|
||||
#ifdef CONFIG_DRM_ROCKCHIP_PANEL
|
||||
extern const struct rockchip_panel_funcs panel_simple_funcs;
|
||||
#endif
|
||||
#ifdef CONFIG_DRM_ROCKCHIP_DSI_PANEL
|
||||
extern const struct rockchip_panel_funcs rockchip_dsi_panel_funcs;
|
||||
#endif
|
||||
#endif /* _ROCKCHIP_PANEL_H_ */
|
||||
|
|
|
|||
Loading…
Reference in New Issue