config EXYNOS_MULTIRESOLUTION
bool "Support Multi Resolution LCD"
depends on EXYNOS_DPU20 && EXYNOS_WINDOW_UPDATE
- default y
+ default n
config EXYNOS_VIRTUAL_DISPLAY
bool "Support Virtual Display Mode"
dpp-y := dpp_drv.o
obj-$(CONFIG_EXYNOS_MIPI_DSIM) += dsim.o
dsim-y += dsim_drv.o
-obj-$(CONFIG_EXYNOS_DISPLAYPORT) += displayport.o
-displayport-y += displayport_drv.o displayport_edid.o displayport_hdcp13.o ./cal_9610/displayport_reg.o
obj-$(CONFIG_SOC_EXYNOS9610) += ./cal_9610/dsim_reg.o ./cal_9610/dpp_reg.o ./cal_9610/decon_reg.o
+ifdef CONFIG_EXYNOS_DISPLAYPORT
+obj-$(CONFIG_EXYNOS_DISPLAYPORT) += displayport.o
+displayport-y += displayport_drv.o displayport_edid.o displayport_hdcp13.o decon_displayport.o
+obj-$(CONFIG_SOC_EXYNOS9610) += ./cal_9610/displayport_reg.o
+endif
obj-$(CONFIG_EXYNOS_DPU20) += decon.o
obj-$(CONFIG_EXYNOS_BTS) += bts.o
decon-y += decon_core.o decon_dsi.o decon_wb.o helper.o win_update.o cursor.o fence.o event_log.o
#include "./panels/decon_lcd.h"
#include "dsim.h"
+#if defined(CONFIG_EXYNOS_DISPLAYPORT)
#include "displayport.h"
+#endif
#if defined(CONFIG_SUPPORT_LEGACY_FENCE)
#include "../../../../dma-buf/sync_debug.h"
#endif
#define MIN_BLK_MODE_HEIGHT 16
#define VSYNC_TIMEOUT_MSEC 200
#define DEFAULT_BPP 32
-#define MIN_WIN_BLOCK_WIDTH 8
-#define MIN_WIN_BLOCK_HEIGHT 1
#define FD_TRY_CNT 3
#define VALID_FD_VAL 3
#define DECON_TRACE_BUF_SIZE 40
u32 id;
u32 start_cnt;
u32 done_cnt;
- u32 comp_src;
+ u32 comp;
+ u32 rot;
+ u32 hdr_std;
struct decon_frame src;
struct decon_frame dst;
};
void decon_wb_set_clocks(struct decon_device *decon);
int decon_wb_get_out_sd(struct decon_device *decon);
+#if defined(CONFIG_EXYNOS_DISPLAYPORT)
/* DECON to DISPLAYPORT interface functions */
int decon_displayport_register_irq(struct decon_device *decon);
void decon_displayport_free_irq(struct decon_device *decon);
struct exynos_displayport_data *displayport_data);
int decon_displayport_set_config(struct decon_device *dex,
struct exynos_displayport_data *displayport_data);
+#endif
/* window update related function */
#define DPU_FULL_RECT(r, lcd) \
#include "./panels/lcd_ctrl.h"
#include "../../../../dma-buf/sync_debug.h"
#include "dpp.h"
+#if defined(CONFIG_EXYNOS_DISPLAYPORT)
#include "displayport.h"
+#endif
int decon_log_level = 6;
module_param(decon_log_level, int, 0644);
#endif
struct dma_buf *buf = NULL;
struct decon_dma_buf_data *dma_buf_data = NULL;
+#if defined(CONFIG_EXYNOS_DISPLAYPORT)
struct displayport_device *displayport;
+#endif
struct dsim_device *dsim;
struct device *dev;
int i;
return PTR_ERR(buf);
}
if (decon->dt.out_type == DECON_OUT_DP) {
+#if defined(CONFIG_EXYNOS_DISPLAYPORT)
displayport = v4l2_get_subdevdata(decon->out_sd[0]);
dev = displayport->dev;
+#endif
} else { /* DSI case */
dsim = v4l2_get_subdevdata(decon->out_sd[0]);
dev = dsim->dev;
return 0;
}
+#if defined(CONFIG_EXYNOS_CONTENT_PATH_PROTECTION)
+ decon_set_protected_content(decon, regs);
+#endif
+
for (i = 0; i < decon->dt.max_win; i++) {
if (regs->is_cursor_win[i]) {
dpu_cursor_win_update_config(decon, regs);
decon_reg_config_wb_size(decon->id, decon->lcd_info, &p);
}
-#if defined(CONFIG_EXYNOS_CONTENT_PATH_PROTECTION)
- decon_set_protected_content(decon, regs);
-#endif
-
decon_reg_all_win_shadow_update_req(decon->id);
decon_to_psr_info(decon, &psr);
if (decon_reg_start(decon->id, &psr) < 0) {
struct decon_reg_data *regs, int win_num, bool on)
{
struct exynos_video_meta *video_meta;
- int ret = 0, hdr_cmp = 0;
+#if defined(CONFIG_EXYNOS_DISPLAYPORT)
+ int ret = 0;
+#endif
+ int hdr_cmp = 0;
int meta_plane = 0;
if (!on) {
hdr_static_info.mid = -1;
decon->prev_hdr_info.mid = -1;
+#if defined(CONFIG_EXYNOS_DISPLAYPORT)
ret = v4l2_subdev_call(decon->displayport_sd, core, ioctl,
DISPLAYPORT_IOC_SET_HDR_METADATA,
&hdr_static_info);
if (ret)
goto err_hdr_io;
-
+#endif
return 0;
}
#endif
hdr_cmp = memcmp(&decon->prev_hdr_info,
- &video_meta->data.dec.shdr_static_info,
+ &video_meta->shdr_static_info,
sizeof(struct exynos_hdr_static_info));
/* HDR metadata is same, so skip subdev call.
#endif
return 0;
}
-
+#if defined(CONFIG_EXYNOS_DISPLAYPORT)
ret = v4l2_subdev_call(decon->displayport_sd, core, ioctl,
DISPLAYPORT_IOC_SET_HDR_METADATA,
- &video_meta->data.dec.shdr_static_info);
+ &video_meta->shdr_static_info);
if (ret)
goto err_hdr_io;
-
+#endif
memcpy(&decon->prev_hdr_info,
- &video_meta->data.dec.shdr_static_info,
+ &video_meta->shdr_static_info,
sizeof(struct exynos_hdr_static_info));
#if !defined(CONFIG_SUPPORT_LEGACY_ION)
dma_buf_vunmap(regs->dma_buf_data[win_num][meta_plane].dma_buf, video_meta);
#endif
return 0;
+#if defined(CONFIG_EXYNOS_DISPLAYPORT)
err_hdr_io:
+#endif
/* When the subdev call is failed,
* current hdr_static_info is not copied to prev.
*/
&win_config[decon->dt.max_win], regs);
}
- for (i = 0; i < decon->dt.dpp_cnt; i++) {
+ for (i = 0; i < (decon->dt.dpp_cnt + 1); i++) {
memcpy(®s->dpp_config[i], &win_config[i],
sizeof(struct decon_win_config));
regs->dpp_config[i].format =
else if (decon->dt.out_type == DECON_OUT_DP)
ret = decon_displayport_get_out_sd(decon);
#endif
+ else
+ ret = -ENODEV;
return ret;
}
static int decon_initial_display(struct decon_device *decon, bool is_colormap)
{
struct decon_param p;
- struct fb_info *fbinfo = decon->win[decon->dt.dft_win]->fbinfo;
+ struct fb_info *fbinfo;
struct decon_window_regs win_regs;
struct decon_win_config config;
struct v4l2_subdev *sd = NULL;
return 0;
}
+ fbinfo = decon->win[decon->dt.dft_win]->fbinfo;
+
pm_stay_awake(decon->dev);
dev_warn(decon->dev, "pm_stay_awake");
char *p = buf;
struct lcd_mres_info *mres_info = &lcd_info->dt_lcd_mres;
int len;
+ struct v4l2_subdev *sd;
+ struct dpp_restriction res;
+ int sz_align = 1;
+
+ sd = decon->dpp_sd[0];
+ v4l2_subdev_call(sd, core, ioctl, DPP_GET_RESTRICTION, &res);
len = sprintf(p, "%d\n", decon->dt.psr_mode);
len += sprintf(p + len, "%d\n", mres_info->mres_number);
len += sprintf(p + len, "%d\n%d\n%d\n%d\n%d\n",
mres_info->res_info[i].width,
mres_info->res_info[i].height,
- MIN_WIN_BLOCK_WIDTH,
- MIN_WIN_BLOCK_HEIGHT,
+ (res.src_f_w.min * sz_align),
+ (res.src_f_h.min * sz_align),
mres_info->res_info[i].dsc_en);
}
return len;
p->addr[3] = 0;
p->eq_mode = config->dpp_parm.eq_mode;
p->hdr = config->dpp_parm.hdr_std;
+ p->max_luminance = config->dpp_parm.max_luminance;
+ p->min_luminance = config->dpp_parm.min_luminance;
p->is_4p = false;
p->y_2b_strd = 0;
p->c_2b_strd = 0;
struct clk *rgb_vclk0;
struct clk *pclk_disp;
struct clk *aclk;
- int lcd_power[2];
+ int lcd_power[3];
int lcd_reset;
int irq;
void __iomem *regs;
dsim_dbg("Short Packet was received from LCD module.\n");
for (i = 0; i <= cnt; i++)
buf[i] = (rx_fifo >> (8 + i * 8)) & 0xff;
+ rx_size = cnt;
break;
case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE:
case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE:
res->lcd_power[1] = -1;
dsim_info("This board doesn't support 2nd LCD power GPIO");
}
+ res->lcd_power[2] = of_get_gpio(dev->of_node, 3);
+ if (res->lcd_power[2] < 0) {
+ res->lcd_power[2] = -1;
+ dsim_info("This board doesn't support 3rd LCD power GPIO");
+ }
}
dsim_info("%s -\n", __func__);
gpio_free(res->lcd_power[1]);
usleep_range(10000, 11000);
}
+ if (res->lcd_power[2] > 0) {
+ ret = gpio_request_one(res->lcd_power[2],
+ GPIOF_OUT_INIT_HIGH, "lcd_power2");
+ if (ret < 0) {
+ dsim_err("failed 3rd LCD power on\n");
+ return -EINVAL;
+ }
+ gpio_free(res->lcd_power[2]);
+ usleep_range(10000, 11000);
+ }
if (res->regulator_1p8v > 0) {
ret = regulator_enable(res->regulator_1p8v);
if (ret) {
gpio_free(res->lcd_power[1]);
usleep_range(5000, 6000);
}
+ if (res->lcd_power[2] > 0) {
+ ret = gpio_request_one(res->lcd_power[2],
+ GPIOF_OUT_INIT_LOW, "lcd_power2");
+ if (ret < 0) {
+ dsim_err("failed 3nd LCD power off\n");
+ return -EINVAL;
+ }
+ gpio_free(res->lcd_power[2]);
+ usleep_range(5000, 6000);
+ }
if (res->regulator_1p8v > 0) {
ret = regulator_disable(res->regulator_1p8v);
if (ret) {
break;
case DPU_EVT_DPP_WINCON:
log->data.dpp.id = dpp->id;
+ log->data.dpp.comp = dpp->dpp_config->config.compression;
+ log->data.dpp.rot = dpp->dpp_config->config.dpp_parm.rot;
+ log->data.dpp.hdr_std = dpp->dpp_config->config.dpp_parm.hdr_std;
memcpy(&log->data.dpp.src, &dpp->dpp_config->config.src, sizeof(struct decon_frame));
memcpy(&log->data.dpp.dst, &dpp->dpp_config->config.dst, sizeof(struct decon_frame));
break;
break;
case DPU_EVT_DPP_WINCON:
seq_printf(s, "%20s ", "DPP_WINCON");
- seq_printf(s, "ID:%d, start= %d, done= %d\n",
+ seq_printf(s, "ID:%d, comp= %d, rot= %d, hdr= %d\n",
log->data.dpp.id,
- log->data.dpp.start_cnt,
- log->data.dpp.done_cnt);
+ log->data.dpp.comp,
+ log->data.dpp.rot,
+ log->data.dpp.hdr_std);
break;
case DPU_EVT_DPP_FRAMEDONE:
seq_printf(s, "%20s ", "DPP_FRAMEDONE");
};
struct exynos_video_dec_data {
- struct exynos_hdr_static_info shdr_static_info;
- struct exynos_color_aspects scolor_aspects;
int ninterlaced_type;
};
struct exynos_video_enc_data {
- struct exynos_hdr_static_info shdr_static_info;
- struct exynos_color_aspects scolor_aspects;
struct exynos_video_ysum_data sysum_data;
};
struct exynos_video_meta {
enum exynos_video_info_type etype;
-
+ /* common */
+ struct exynos_hdr_static_info shdr_static_info;
+ struct exynos_color_aspects scolor_aspects;
union {
struct exynos_video_dec_data dec;
struct exynos_video_enc_data enc;
#include "decon.h"
#include "dsim.h"
#include "dpp.h"
+#if defined(CONFIG_EXYNOS_DISPLAYPORT)
#include "displayport.h"
+#endif
#include "./panels/lcd_ctrl.h"
#include <video/mipi_display.h>
{
struct dpp_device *dpp;
struct dsim_device *dsim;
+#if defined(CONFIG_EXYNOS_DISPLAYPORT)
struct displayport_device *displayport;
+#endif
struct decon_device *decon = (struct decon_device *)data;
decon_dbg("%s: drvname(%s)\n", __func__, dev->driver->name);
dsim = (struct dsim_device *)dev_get_drvdata(dev);
decon->dsim_sd[dsim->id] = &dsim->sd;
decon_dbg("dsim sd name(%s)\n", dsim->sd.name);
+#if defined(CONFIG_EXYNOS_DISPLAYPORT)
} else if (!strcmp(DISPLAYPORT_MODULE_NAME, dev->driver->name)) {
displayport = (struct displayport_device *)dev_get_drvdata(dev);
decon->displayport_sd = &displayport->sd;
decon_dbg("displayport sd name(%s)\n", displayport->sd.name);
+#endif
} else {
decon_err("failed to get driver name\n");
}
if (!strcmp(DSIM_MODULE_NAME, dev->driver->name)) {
decon = get_decon_drvdata(0);
+#if defined(CONFIG_EXYNOS_DISPLAYPORT)
} else if (!strcmp(DISPLAYPORT_MODULE_NAME, dev->driver->name)) {
decon = get_decon_drvdata(2);
+#endif
} else {
decon_err("unknown driver for dpu sysmmu falut handler(%s)\n",
dev->driver->name);
struct decon_win_config *update_config = &win_config[DECON_WIN_UPDATE_IDX];
struct decon_win_config *config;
struct decon_frame adj_region;
+ struct v4l2_subdev *sd;
+ struct dpp_restriction res;
+ u32 min_src_w, min_src_h;
+ int sz_align = 1;
regs->need_update = false;
DPU_FULL_RECT(®s->up_region, decon->lcd_info);
r2.bottom = div_h * decon->win_up.rect_h - 1;
/* TODO: Now, 4 slices must be used. This will be modified */
- r2.left = 0;
- r2.right = decon->lcd_info->xres - 1;
+ if (decon->lcd_info->dsc_enabled) {
+ r2.left = 0;
+ r2.right = decon->lcd_info->xres - 1;
+ } else {
+ sd = decon->dpp_sd[0];
+ v4l2_subdev_call(sd, core, ioctl, DPP_GET_RESTRICTION, &res);
+
+ min_src_w = res.src_f_w.min * sz_align;
+ min_src_h = res.src_f_h.min * sz_align;
+
+ if (decon->lcd_info->xres - r2.left < min_src_w)
+ r2.left = ((r1.left - min_src_w) / decon->win_up.rect_w) *
+ decon->win_up.rect_w;
+ if (decon->lcd_info->yres - r2.top < min_src_h)
+ r2.top = ((r1.top - min_src_h) / decon->win_up.rect_h) *
+ decon->win_up.rect_h;
+
+ if (decon->lcd_info->xres < r2.right)
+ r2.right = decon->lcd_info->xres - 1;
+ if (decon->lcd_info->yres < r2.bottom)
+ r2.bottom = decon->lcd_info->yres - 1;
+ }
memcpy(®s->up_region, &r2, sizeof(struct decon_rect));
void dpu_init_win_update(struct decon_device *decon)
{
struct decon_lcd *lcd = decon->lcd_info;
+ struct v4l2_subdev *sd;
+ struct dpp_restriction res;
+ int sz_align = 1;
decon->win_up.enabled = false;
decon->cursor.xpos = lcd->xres / 2;
return;
}
+ sd = decon->dpp_sd[0];
+ v4l2_subdev_call(sd, core, ioctl, DPP_GET_RESTRICTION, &res);
+
if (lcd->dsc_enabled) {
decon->win_up.rect_w = lcd->xres / lcd->dsc_slice_num;
decon->win_up.rect_h = lcd->dsc_slice_h;
} else {
- decon->win_up.rect_w = MIN_WIN_BLOCK_WIDTH;
- decon->win_up.rect_h = MIN_WIN_BLOCK_HEIGHT;
+ decon->win_up.rect_w = res.src_f_w.min * sz_align;
+ decon->win_up.rect_h = res.src_f_h.min * sz_align;
}
DPU_FULL_RECT(&decon->win_up.prev_up_region, lcd);
decon->win_up.hori_cnt = decon->lcd_info->xres / decon->win_up.rect_w;
- if (decon->lcd_info->xres - decon->win_up.hori_cnt * decon->win_up.rect_w) {
- decon_warn("%s: parameters is wrong. lcd w(%d), win rect w(%d)\n",
- __func__, decon->lcd_info->xres,
- decon->win_up.rect_w);
- return;
+ if (lcd->dsc_enabled) {
+ if (decon->lcd_info->xres - decon->win_up.hori_cnt * decon->win_up.rect_w) {
+ decon_warn("%s: parameters is wrong. lcd w(%d), win rect w(%d)\n",
+ __func__, decon->lcd_info->xres,
+ decon->win_up.rect_w);
+ return;
+ }
}
decon->win_up.verti_cnt = decon->lcd_info->yres / decon->win_up.rect_h;
- if (decon->lcd_info->yres - decon->win_up.verti_cnt * decon->win_up.rect_h) {
- decon_warn("%s: parameters is wrong. lcd h(%d), win rect h(%d)\n",
- __func__, decon->lcd_info->yres,
- decon->win_up.rect_h);
- return;
+ if (lcd->dsc_enabled) {
+ if (decon->lcd_info->yres - decon->win_up.verti_cnt * decon->win_up.rect_h) {
+ decon_warn("%s: parameters is wrong. lcd h(%d), win rect h(%d)\n",
+ __func__, decon->lcd_info->yres,
+ decon->win_up.rect_h);
+ return;
+ }
}
decon_info("window update is enabled: win rectangle w(%d), h(%d)\n",