case YUV422_A:
case YUV420_A:
case YUV444_A:
- pixel_width = 10;
+ pixel_width = 8;
break;
default:
printk(KERN_WARNING "%s:un supported format:0x%x\n",
enum of_gpio_flags flags;
u32 val = 0;
u32 debug = 0;
- u32 mirror = 0;
int ret;
INIT_LIST_HEAD(&dev_drv->pwrlist_head);
list_add_tail(&pwr_ctr->list, &dev_drv->pwrlist_head);
}
- of_property_read_u32(root, "rockchip,mirror", &mirror);
-
- if (mirror == NO_MIRROR) {
- dev_drv->screen0->x_mirror = 0;
- dev_drv->screen0->y_mirror = 0;
- } else if (mirror == X_MIRROR) {
- dev_drv->screen0->x_mirror = 1;
- dev_drv->screen0->y_mirror = 0;
- } else if (mirror == Y_MIRROR) {
- dev_drv->screen0->x_mirror = 0;
- dev_drv->screen0->y_mirror = 1;
- } else if (mirror == X_Y_MIRROR) {
- dev_drv->screen0->x_mirror = 1;
- dev_drv->screen0->y_mirror = 1;
- }
-
of_property_read_u32(root, "rockchip,debug", &debug);
if (debug) {
return dev_drv;
}
-int rk_fb_get_prmry_screen_ft(void)
+/*
+ * get one frame time of the prmry screen, unit: us
+ */
+u32 rk_fb_get_prmry_screen_ft(void)
{
struct rk_lcdc_driver *dev_drv = rk_get_prmry_lcdc_drv();
- uint32_t htotal, vtotal, pix_total, ft_us, pixclock_ns;
+ uint32_t htotal, vtotal, pixclock_ps;
+ u64 pix_total, ft_us;
if (unlikely(!dev_drv))
return 0;
- pixclock_ns = dev_drv->pixclock / 1000;
+ pixclock_ps = dev_drv->pixclock;
- htotal = (dev_drv->cur_screen->mode.upper_margin +
+ vtotal = (dev_drv->cur_screen->mode.upper_margin +
dev_drv->cur_screen->mode.lower_margin +
dev_drv->cur_screen->mode.yres +
dev_drv->cur_screen->mode.vsync_len);
- vtotal = (dev_drv->cur_screen->mode.left_margin +
+ htotal = (dev_drv->cur_screen->mode.left_margin +
+ dev_drv->cur_screen->mode.right_margin +
+ dev_drv->cur_screen->mode.xres +
+ dev_drv->cur_screen->mode.hsync_len);
+ pix_total = htotal * vtotal;
+ ft_us = pix_total * pixclock_ps;
+ do_div(ft_us, 1000000);
+ if (dev_drv->frame_time.ft == 0)
+ dev_drv->frame_time.ft = ft_us;
+
+ ft_us = dev_drv->frame_time.framedone_t - dev_drv->frame_time.last_framedone_t;
+ do_div(ft_us, 1000);
+ ft_us = min(dev_drv->frame_time.ft, (u32)ft_us);
+ if (ft_us != 0)
+ dev_drv->frame_time.ft = ft_us;
+
+ return dev_drv->frame_time.ft;
+}
+
+/*
+ * get the vblanking time of the prmry screen, unit: us
+ */
+u32 rk_fb_get_prmry_screen_vbt(void)
+{
+ struct rk_lcdc_driver *dev_drv = rk_get_prmry_lcdc_drv();
+ uint32_t htotal, vblank, pixclock_ps;
+ u64 pix_blank, vbt_us;
+
+ if (unlikely(!dev_drv))
+ return 0;
+
+ pixclock_ps = dev_drv->pixclock;
+
+ htotal = (dev_drv->cur_screen->mode.left_margin +
dev_drv->cur_screen->mode.right_margin +
dev_drv->cur_screen->mode.xres +
dev_drv->cur_screen->mode.hsync_len);
- pix_total = htotal * vtotal / 1000;
- ft_us = pix_total * pixclock_ns;
- return ft_us;
+ vblank = (dev_drv->cur_screen->mode.upper_margin +
+ dev_drv->cur_screen->mode.lower_margin +
+ dev_drv->cur_screen->mode.vsync_len);
+ pix_blank = htotal * vblank;
+ vbt_us = pix_blank * pixclock_ps;
+ do_div(vbt_us, 1000000);
+ return (u32)vbt_us;
+}
+
+/*
+ * get the frame done time of the prmry screen, unit: us
+ */
+u64 rk_fb_get_prmry_screen_framedone_t(void)
+{
+ struct rk_lcdc_driver *dev_drv = rk_get_prmry_lcdc_drv();
+
+ if (unlikely(!dev_drv))
+ return 0;
+ else
+ return dev_drv->frame_time.framedone_t;
+}
+
+/*
+ * set prmry screen status
+ */
+int rk_fb_set_prmry_screen_status(int status)
+{
+ struct rk_lcdc_driver *dev_drv = rk_get_prmry_lcdc_drv();
+ struct rk_screen *screen;
+
+ if (unlikely(!dev_drv))
+ return 0;
+
+ screen = dev_drv->cur_screen;
+ switch (status) {
+ case SCREEN_PREPARE_DDR_CHANGE:
+ if (screen->type == SCREEN_MIPI
+ || screen->type == SCREEN_DUAL_MIPI) {
+ if (dev_drv->trsm_ops->dsp_pwr_off)
+ dev_drv->trsm_ops->dsp_pwr_off();
+ }
+ break;
+ case SCREEN_UNPREPARE_DDR_CHANGE:
+ if (screen->type == SCREEN_MIPI
+ || screen->type == SCREEN_DUAL_MIPI) {
+ if (dev_drv->trsm_ops->dsp_pwr_on)
+ dev_drv->trsm_ops->dsp_pwr_on();
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 0;
}
static struct rk_lcdc_driver *rk_get_extend_lcdc_drv(void)
u32 rk_fb_get_prmry_screen_pixclock(void)
{
struct rk_lcdc_driver *dev_drv = rk_get_prmry_lcdc_drv();
- return dev_drv->pixclock;
+
+ if (unlikely(!dev_drv))
+ return 0;
+ else
+ return dev_drv->pixclock;
}
int rk_fb_poll_prmry_screen_vblank(void)
}
return false;
}
-
while (!(rk_fb_poll_prmry_screen_vblank() == RK_LF_STATUS_FR) && --timeout)
;
while (!(rk_fb_poll_prmry_screen_vblank() == RK_LF_STATUS_FC) && --timeout)
;
-
if (likely(dev_drv)) {
if (dev_drv->ops->set_irq_to_cpu)
dev_drv->ops->set_irq_to_cpu(dev_drv, 1);
return 0;
}
+
#if defined(CONFIG_RK29_IPP)
static int get_ipp_format(int fmt)
{
int dst_w, dst_h, dst_vir_w;
int ipp_fmt;
u8 data_format = (dst_info->var.nonstd) & 0xff;
+ struct rk_lcdc_driver *ext_dev_drv =
+ (struct rk_lcdc_driver *)dst_info->par;
+ u16 orientation = ext_dev_drv->rotate_mode;
memset(&ipp_req, 0, sizeof(struct rk29_ipp_req));
-#if defined(CONFIG_FB_ROTATE)
- int orientation = 270 - CONFIG_ROTATE_ORIENTATION;
+
switch (orientation) {
case 0:
rotation = IPP_ROT_0;
break;
- case 90:
+ case ROTATE_90:
rotation = IPP_ROT_90;
break;
- case 180:
+ case ROTATE_180:
rotation = IPP_ROT_180;
break;
- case 270:
+ case ROTATE_270:
rotation = IPP_ROT_270;
break;
default:
break;
}
-#endif
dst_w = dst_info->var.xres;
dst_h = dst_info->var.yres;
}
static void win_copy_by_rga(struct rk_lcdc_win *dst_win,
- struct rk_lcdc_win *src_win)
+ struct rk_lcdc_win *src_win, u16 orientation)
{
- struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
struct rga_req Rga_Request;
long ret = 0;
/* int fd = 0; */
-#if defined(CONFIG_FB_ROTATE)
- int orientation = 0;
-#endif
memset(&Rga_Request, 0, sizeof(Rga_Request));
rga_win_check(dst_win, src_win);
-#if defined(CONFIG_FB_ROTATE)
- orientation = 270 - CONFIG_ROTATE_ORIENTATION;
switch (orientation) {
- case 90:
+ case ROTATE_90:
Rga_Request.rotate_mode = 1;
Rga_Request.sina = 65536;
Rga_Request.cosa = 0;
Rga_Request.dst.x_offset = dst_win->area[0].xact - 1;
Rga_Request.dst.y_offset = 0;
break;
- case 180:
+ case ROTATE_180:
Rga_Request.rotate_mode = 1;
Rga_Request.sina = 0;
Rga_Request.cosa = -65536;
Rga_Request.dst.x_offset = dst_win->area[0].xact - 1;
Rga_Request.dst.y_offset = dst_win->area[0].yact - 1;
break;
- case 270:
+ case ROTATE_270:
Rga_Request.rotate_mode = 1;
Rga_Request.sina = -65536;
Rga_Request.cosa = 0;
Rga_Request.dst.act_w = dst_win->area[0].yact;
Rga_Request.dst.act_h = dst_win->area[0].xact;
- Rga_Request.dst.x_offset = dst_win->area[0].xact - 1;
+ Rga_Request.dst.x_offset = 0;
Rga_Request.dst.y_offset = dst_win->area[0].yact - 1;
break;
default:
Rga_Request.dst.y_offset = dst_win->area[0].yact - 1;
break;
}
-#endif
#if defined(CONFIG_ROCKCHIP_RGA)
Rga_Request.src.yrgb_addr =
Rga_Request.src.uv_addr = 0;
Rga_Request.src.v_addr = 0;
- dst_win->area[0].smem_start =
- rk_fb->fb[rk_fb->num_fb >> 1]->fix.smem_start;
Rga_Request.dst.yrgb_addr =
dst_win->area[0].smem_start + dst_win->area[0].y_offset;
Rga_Request.dst.uv_addr = 0;
src_win->area[0].smem_start + src_win->area[0].y_offset;
Rga_Request.src.v_addr = 0;
- dst_win->area[0].smem_start =
- rk_fb->fb[rk_fb->num_fb >> 1]->fix.smem_start;
Rga_Request.dst.yrgb_addr = 0;
Rga_Request.dst.uv_addr =
dst_win->area[0].smem_start + dst_win->area[0].y_offset;
ext_dev_drv->ops->fb_get_win_id(ext_dev_drv, dst_info->fix.id);
dst_win = ext_dev_drv->win[ext_win_id];
- win_copy_by_rga(dst_win, src_win);
+ win_copy_by_rga(dst_win, src_win, ext_dev_drv->rotate_mode);
}
#endif
-#if defined(CONFIG_FB_ROTATE) || !defined(CONFIG_THREE_FB_BUFFER)
static int rk_fb_rotate(struct fb_info *dst_info,
struct fb_info *src_info, int offset)
{
}
static int rk_fb_win_rotate(struct rk_lcdc_win *dst_win,
- struct rk_lcdc_win *src_win)
+ struct rk_lcdc_win *src_win, u16 rotate)
{
#if defined(CONFIG_ROCKCHIP_RGA) || defined(CONFIG_ROCKCHIP_RGA2)
- win_copy_by_rga(dst_win, src_win);
+ win_copy_by_rga(dst_win, src_win, rotate);
#else
return -1;
#endif
return 0;
}
-#endif
+
static int rk_fb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
if (rk_fb->disp_mode == DUAL) {
if (extend_win->state && (hdmi_switch_complete)) {
extend_win->area[0].y_offset = win->area[0].y_offset;
-#if defined(CONFIG_FB_ROTATE) || !defined(CONFIG_THREE_FB_BUFFER)
- rk_fb_rotate(extend_info, info, win->area[0].y_offset);
-#else
- extend_win->area[0].smem_start = win->area[0].smem_start;
- extend_win->area[0].cbr_start = win->area[0].cbr_start;
-#endif
+ if (extend_dev_drv->rotate_mode > X_Y_MIRROR) {
+ rk_fb_rotate(extend_info, info,
+ win->area[0].y_offset);
+ } else {
+ extend_win->area[0].smem_start =
+ win->area[0].smem_start;
+ extend_win->area[0].cbr_start =
+ win->area[0].cbr_start;
+ }
extend_dev_drv->ops->pan_display(extend_dev_drv,
extend_win_id);
}
struct rk_fb_reg_win_data *reg_win_data)
{
int i = 0;
-/*
- struct rk_lcdc_win *win;
- win = dev_drv->win[reg_win_data->win_id];
-*/
+
win->area_num = reg_win_data->area_num;
win->format = reg_win_data->data_format;
win->id = reg_win_data->win_id;
win->z_order = reg_win_data->z_order;
win->area[0].uv_vir_stride =
reg_win_data->reg_area_data[0].uv_vir_stride;
-
-#if !defined(RK_FB_ROTATE) && defined(CONFIG_THREE_FB_BUFFER)
- /* TODO Mofidy if HDMI info is change to hwc */
win->area[0].cbr_start =
reg_win_data->reg_area_data[0].cbr_start;
-#endif
win->area[0].c_offset = reg_win_data->reg_area_data[0].c_offset;
win->alpha_en = reg_win_data->alpha_en;
win->alpha_mode = reg_win_data->alpha_mode;
win->g_alpha_val = reg_win_data->g_alpha_val;
for (i = 0; i < RK_WIN_MAX_AREA; i++) {
if (reg_win_data->reg_area_data[i].smem_start > 0) {
-#if !defined(RK_FB_ROTATE) && defined(CONFIG_THREE_FB_BUFFER)
win->area[i].smem_start =
reg_win_data->reg_area_data[i].smem_start;
-#endif
win->area[i].xpos =
reg_win_data->reg_area_data[i].xpos;
win->area[i].ypos =
}
+static int rk_fb_update_hdmi_win(struct rk_lcdc_win *ext_win,
+ struct rk_lcdc_win *win)
+{
+ struct rk_fb *rk_fb = platform_get_drvdata(fb_pdev);
+ struct rk_lcdc_driver *dev_drv = rk_get_prmry_lcdc_drv();
+ struct rk_lcdc_driver *ext_dev_drv = rk_get_extend_lcdc_drv();
+ struct rk_screen *screen;
+ struct rk_screen *ext_screen;
+ int hdmi_xsize;
+ int hdmi_ysize;
+ int pixel_width, vir_width_bit, y_stride;
+ struct rk_lcdc_win *last_win;
+ bool is_yuv = false;
+ static u8 fb_index = 0;
+
+ if ((rk_fb->disp_mode != DUAL) ||
+ (hdmi_get_hotplug() != HDMI_HPD_ACTIVED) ||
+ (!hdmi_switch_complete)) {
+ printk(KERN_INFO "%s: hdmi is disconnect!\n", __func__);
+ return -1;
+ }
+
+ if (unlikely(!dev_drv) || unlikely(!ext_dev_drv))
+ return -1;
+
+ screen = dev_drv->cur_screen;
+ ext_screen = ext_dev_drv->cur_screen;
+ hdmi_xsize = ext_screen->xsize;
+ hdmi_ysize = ext_screen->ysize;
+
+ ext_win->state = win->state;
+ ext_win->id = win->id;
+ if (win->area[0].smem_start == 0)
+ ext_win->state = 0;
+ if (ext_win->state == 0)
+ return 0;
+
+ ext_win->area_num = win->area_num;
+ ext_win->format = win->format;
+ ext_win->z_order = win->z_order;
+ ext_win->alpha_en = win->alpha_en;
+ ext_win->alpha_mode = win->alpha_mode;
+ ext_win->g_alpha_val = win->g_alpha_val;
+
+ /* win0 and win1 have only one area and support scale
+ * but win2 and win3 don't support scale
+ * so hdmi only use win0 or win1
+ */
+ ext_win->area[0].state = win->area[0].state;
+
+ switch (ext_win->format) {
+ case YUV422:
+ case YUV420:
+ case YUV444:
+ case YUV422_A:
+ case YUV420_A:
+ case YUV444_A:
+ is_yuv = true;
+ break;
+ default:
+ is_yuv = false;
+ break;
+ }
+
+ if (ext_dev_drv->rotate_mode == ROTATE_90 ||
+ ext_dev_drv->rotate_mode == ROTATE_270) {
+ if (ext_win->id == 0) {
+ ext_win->area[0].smem_start =
+ rk_fb->fb[rk_fb->num_fb >> 1]->fix.smem_start;
+ ext_win->area[0].y_offset = (get_fb_size() >> 1) * fb_index;
+ if ((++fb_index) > 1)
+ fb_index = 0;
+ } else {
+ ext_win->area[0].y_offset = 0;
+ last_win = ext_dev_drv->win[ext_win->id - 1];
+ if (last_win->area[0].cbr_start)
+ ext_win->area[0].smem_start =
+ last_win->area[0].cbr_start +
+ last_win->area[0].c_offset +
+ last_win->area[0].xvir * last_win->area[0].yvir;
+ else
+ ext_win->area[0].smem_start =
+ last_win->area[0].smem_start +
+ last_win->area[0].y_offset +
+ last_win->area[0].xvir * last_win->area[0].yvir;
+ }
+
+ ext_win->area[0].xact = win->area[0].yact;
+ ext_win->area[0].yact = win->area[0].xact;
+ ext_win->area[0].xvir = win->area[0].yact;
+ ext_win->area[0].yvir = win->area[0].xact;
+ pixel_width = rk_fb_pixel_width(ext_win->format);
+ vir_width_bit = pixel_width * ext_win->area[0].xvir;
+ y_stride = ALIGN_N_TIMES(vir_width_bit, 32) / 8;
+ ext_win->area[0].y_vir_stride = y_stride >> 2;
+ } else {
+ ext_win->area[0].smem_start = win->area[0].smem_start;
+ ext_win->area[0].y_offset = win->area[0].y_offset;
+ ext_win->area[0].xact = win->area[0].xact;
+ ext_win->area[0].yact = win->area[0].yact;
+ ext_win->area[0].xvir = win->area[0].xvir;
+ ext_win->area[0].yvir = win->area[0].yvir;
+ ext_win->area[0].y_vir_stride = win->area[0].y_vir_stride;
+ }
+
+ if (win->area[0].xpos != 0 || win->area[0].ypos != 0) {
+ if (ext_dev_drv->rotate_mode == ROTATE_270) {
+ int xbom_pos = 0, ybom_pos = 0;
+ int xtop_pos = 0, ytop_pos = 0;
+
+ ext_win->area[0].xsize = hdmi_xsize *
+ win->area[0].ysize /
+ screen->mode.yres;
+ ext_win->area[0].ysize = hdmi_ysize *
+ win->area[0].xsize /
+ screen->mode.xres;
+ xbom_pos = hdmi_xsize * win->area[0].ypos / screen->mode.yres;
+ ybom_pos = hdmi_ysize * win->area[0].xpos / screen->mode.xres;
+ xtop_pos = hdmi_xsize - ext_win->area[0].xsize - xbom_pos;
+ ytop_pos = hdmi_ysize - ext_win->area[0].ysize - ybom_pos;
+ ext_win->area[0].xpos =
+ ((ext_screen->mode.xres - hdmi_xsize) >> 1) + xtop_pos;
+ ext_win->area[0].ypos =
+ ((ext_screen->mode.yres - hdmi_ysize) >> 1) + ytop_pos;
+ } else if (ext_dev_drv->rotate_mode == ROTATE_90) {
+ ext_win->area[0].xsize = hdmi_xsize *
+ win->area[0].ysize /
+ screen->mode.yres;
+ ext_win->area[0].ysize = hdmi_ysize *
+ win->area[0].xsize /
+ screen->mode.xres;
+ ext_win->area[0].xpos =
+ ((ext_screen->mode.xres - hdmi_xsize) >> 1) +
+ hdmi_xsize * win->area[0].ypos / screen->mode.yres;
+ ext_win->area[0].ypos =
+ ((ext_screen->mode.yres - hdmi_ysize) >> 1) +
+ hdmi_ysize * win->area[0].xpos / screen->mode.xres;
+ } else {
+ ext_win->area[0].xsize = hdmi_xsize *
+ win->area[0].xsize /
+ screen->mode.xres;
+ ext_win->area[0].ysize = hdmi_ysize *
+ win->area[0].ysize /
+ screen->mode.yres;
+ ext_win->area[0].xpos =
+ ((ext_screen->mode.xres - hdmi_xsize) >> 1) +
+ hdmi_xsize * win->area[0].xpos / screen->mode.xres;
+ ext_win->area[0].ypos =
+ ((ext_screen->mode.yres - hdmi_ysize) >> 1) +
+ hdmi_ysize * win->area[0].ypos / screen->mode.yres;
+ }
+ } else {
+ ext_win->area[0].xsize = hdmi_xsize;
+ ext_win->area[0].ysize = hdmi_ysize;
+ ext_win->area[0].xpos =
+ (ext_screen->mode.xres - hdmi_xsize) >> 1;
+ ext_win->area[0].ypos =
+ (ext_screen->mode.yres - hdmi_ysize) >> 1;
+ }
+
+ if (!is_yuv) {
+ ext_win->area[0].uv_vir_stride = 0;
+ ext_win->area[0].cbr_start = 0;
+ ext_win->area[0].c_offset = 0;
+ return 0;
+ }
+
+ if (ext_dev_drv->rotate_mode == ROTATE_90 ||
+ ext_dev_drv->rotate_mode == ROTATE_270) {
+ ext_win->area[0].uv_vir_stride = ext_win->area[0].y_vir_stride;
+ ext_win->area[0].cbr_start = ext_win->area[0].smem_start +
+ ext_win->area[0].y_offset +
+ ext_win->area[0].xvir * ext_win->area[0].yvir;
+ ext_win->area[0].c_offset = win->area[0].c_offset;
+ } else {
+ ext_win->area[0].uv_vir_stride = win->area[0].uv_vir_stride;
+ ext_win->area[0].cbr_start = win->area[0].cbr_start;
+ ext_win->area[0].c_offset = win->area[0].c_offset;
+ }
+
+ return 0;
+}
+
static struct rk_fb_reg_win_data *rk_fb_get_win_data(struct rk_fb_reg_data
*regs, int win_id)
{
struct rk_lcdc_driver *ext_dev_drv;
struct rk_lcdc_win *ext_win;
struct rk_fb_reg_win_data *win_data;
- struct rk_fb_reg_win_data *last_win_data;
bool wait_for_vsync;
int count = 100;
unsigned int dsp_addr[4];
if ((rk_fb->disp_mode == DUAL)
&& (hdmi_get_hotplug() == HDMI_HPD_ACTIVED)
&& hdmi_switch_complete) {
- for (i = 0; i < rk_fb->num_lcdc; i++) {
- if (rk_fb->lcdc_dev_drv[i]->prop == EXTEND) {
- ext_dev_drv = rk_fb->lcdc_dev_drv[i];
- break;
- }
- }
- if (i == rk_fb->num_lcdc) {
- printk(KERN_ERR "hdmi lcdc driver not found!\n");
- goto ext_win_exit;
- }
- /* hdmi just need set win0 only(win0 have only one area)
- * other win is disable
- */
- win = dev_drv->win[0];
- ext_win = ext_dev_drv->win[0];
- for (j = 0; j < regs->win_num; j++) {
- if (0 == regs->reg_win_data[j].win_id)
- break;
- }
- if (j < regs->win_num) {
- rk_fb_update_driver(ext_win, ®s->reg_win_data[j]);
- if (win->area[0].xpos != 0 || win->area[0].ypos != 0) {
- ext_win->area[0].xsize =
- (ext_dev_drv->cur_screen->xsize * win->area[0].xsize) /
- dev_drv->cur_screen->mode.xres;
- ext_win->area[0].ysize =
- (ext_dev_drv->cur_screen->ysize * win->area[0].ysize) /
- dev_drv->cur_screen->mode.yres;
- ext_win->area[0].xpos =
- ((ext_dev_drv->cur_screen->mode.xres - ext_dev_drv->cur_screen->xsize) >> 1) +
- ext_dev_drv->cur_screen->xsize * win->area[0].xpos / dev_drv->cur_screen->mode.xres;
- ext_win->area[0].ypos =
- ((ext_dev_drv->cur_screen->mode.yres - ext_dev_drv->cur_screen->ysize) >> 1) +
- ext_dev_drv->cur_screen->ysize * win->area[0].ypos / dev_drv->cur_screen->mode.yres;
- } else {
- ext_win->area[0].xpos =
- (ext_dev_drv->cur_screen->mode.xres - ext_dev_drv->cur_screen->xsize) >> 1;
- ext_win->area[0].ypos =
- (ext_dev_drv->cur_screen->mode.yres - ext_dev_drv->cur_screen->ysize) >> 1;
- ext_win->area[0].xsize = ext_dev_drv->cur_screen->xsize;
- ext_win->area[0].ysize = ext_dev_drv->cur_screen->ysize;
- }
- /* hdmi only one win so disable alpha */
- ext_win->alpha_en = 0;
- ext_win->state = 1;
- } else {
- ext_win->state = 0;
- }
+ ext_dev_drv = rk_get_extend_lcdc_drv();
+ if (!ext_dev_drv) {
+ printk(KERN_ERR "hdmi lcdc driver not found!\n");
+ goto ext_win_exit;
+ }
+
+ /* win0 and win1 have only one area and support scale
+ * but win2 and win3 don't support scale
+ * so hdmi only use win0 or win1
+ */
+ for (i = 0; i < 2; i++) {
+ win = dev_drv->win[i];
+ ext_win = ext_dev_drv->win[i];
+ ext_win->state = win->state;
+ if (!ext_win->state)
+ continue;
+
+ rk_fb_update_hdmi_win(ext_win, win);
+
+ if (ext_dev_drv->rotate_mode > X_Y_MIRROR)
+ rk_fb_win_rotate(ext_win, win,
+ ext_dev_drv->rotate_mode);
+
+ ext_dev_drv->ops->set_par(ext_dev_drv, i);
+ ext_dev_drv->ops->pan_display(ext_dev_drv, i);
+ }
- if (ext_win->area[0].xact < ext_win->area[0].yact) {
- ext_win->area[0].xact = win->area[0].yact;
- ext_win->area[0].yact = win->area[0].xact;
- ext_win->area[0].xvir = win->area[0].yact;
- }
-#if defined(CONFIG_FB_ROTATE) || !defined(CONFIG_THREE_FB_BUFFER)
- rk_fb_win_rotate(ext_win, win);
-#endif
- ext_dev_drv->ops->set_par(ext_dev_drv, 0);
- ext_dev_drv->ops->pan_display(ext_dev_drv, 0);
ext_dev_drv->ops->cfg_done(ext_dev_drv);
}
ext_win_exit:
g_last_win_num = regs->win_num;
g_first_buf = 0;
- if (dev_drv->wait_fs == 1)
- kfree(regs);
}
static void rk_fb_update_regs_handler(struct kthread_work *work)
list_del(&data->list);
kfree(data);
}
+
+ if (dev_drv->wait_fs && list_empty(&dev_drv->update_regs_list))
+ wake_up(&dev_drv->update_regs_wait);
}
static int rk_fb_check_config_var(struct rk_fb_area_par *area_par,
struct sync_pt *retire_sync_pt;
char fence_name[20];
#endif
- int ret, i, j = 0;
+ int ret = 0, i, j = 0;
+ int list_is_empty = 0;
regs = kzalloc(sizeof(struct rk_fb_reg_data), GFP_KERNEL);
if (!regs) {
mutex_lock(&dev_drv->output_lock);
if (!(dev_drv->suspend_flag == 0)) {
rk_fb_update_reg(dev_drv, regs);
+ kfree(regs);
printk(KERN_INFO "suspend_flag = 1\n");
goto err;
}
queue_kthread_work(&dev_drv->update_regs_worker,
&dev_drv->update_regs_work);
} else {
- rk_fb_update_reg(dev_drv, regs);
+ mutex_lock(&dev_drv->update_regs_list_lock);
+ list_is_empty = list_empty(&dev_drv->update_regs_list) &&
+ list_empty(&saved_list);
+ mutex_unlock(&dev_drv->update_regs_list_lock);
+ if (!list_is_empty) {
+ ret = wait_event_timeout(dev_drv->update_regs_wait,
+ list_empty(&dev_drv->update_regs_list) && list_empty(&saved_list),
+ msecs_to_jiffies(60));
+ if (ret > 0)
+ rk_fb_update_reg(dev_drv, regs);
+ else
+ printk("%s: wait update_regs_wait timeout\n", __func__);
+ } else if (ret == 0) {
+ rk_fb_update_reg(dev_drv, regs);
+ }
+ kfree(regs);
}
err:
int rk_get_real_fps(int before)
{
- if (before > 100)
- before = 100;
- if (before < 0)
- before = 0;
-
struct timespec now;
- getnstimeofday(&now);
- int dist_curr =
- (now.tv_sec * 1000000 + now.tv_nsec / 1000) - cfgdone_lasttime;
+ int dist_curr;
int dist_total = 0;
int dist_count = 0;
int dist_first = 0;
int index = cfgdone_index;
int i = 0, fps = 0;
- int total = dist_curr;
+ int total;
+
+ if (before > 100)
+ before = 100;
+ if (before < 0)
+ before = 0;
+ getnstimeofday(&now);
+ dist_curr = (now.tv_sec * 1000000 + now.tv_nsec / 1000) -
+ cfgdone_lasttime;
+ total = dist_curr;
/*
printk("fps: ");
*/
memcpy(dev_drv->cur_screen, screen, sizeof(struct rk_screen));
}
+ dev_drv->cur_screen->x_mirror = dev_drv->rotate_mode & X_MIRROR;
+ dev_drv->cur_screen->y_mirror = dev_drv->rotate_mode & Y_MIRROR;
+
win_id = dev_drv->ops->fb_get_win_id(dev_drv, info->fix.id);
if (!enable && !dev_drv->screen1) { /* only double lcdc device need to close */
int win_id;
int ret = 0;
unsigned long fb_mem_size;
-/*
-#if defined(CONFIG_FB_ROTATE) || !defined(CONFIG_THREE_FB_BUFFER)
- struct resource *res;
- struct resource *mem;
+#if !defined(CONFIG_ION_ROCKCHIP)
+ dma_addr_t fb_mem_phys;
+ void *fb_mem_virt;
#endif
-*/
+
win_id = dev_drv->ops->fb_get_win_id(dev_drv, fbi->fix.id);
if (win_id < 0)
return -ENODEV;
if (rk_fb_alloc_buffer_by_ion(fbi, win, fb_mem_size) < 0)
return -ENOMEM;
#else
- dma_addr_t fb_mem_phys;
- void *fb_mem_virt;
fb_mem_virt = dma_alloc_writecombine(fbi->dev, fb_mem_size,
&fb_mem_phys, GFP_KERNEL);
if (!fb_mem_virt) {
fbi->fix.smem_start, fbi->screen_base,
fbi->fix.smem_len);
} else {
-#if defined(CONFIG_FB_ROTATE) || !defined(CONFIG_THREE_FB_BUFFER)
- /*
- res = platform_get_resource_byname(fb_pdev,
- IORESOURCE_MEM, "fb2 buf");
- if (res == NULL) {
- dev_err(&fb_pdev->dev, "failed to get win0 memory\n");
- ret = -ENOENT;
- }
- fbi->fix.smem_start = res->start;
- fbi->fix.smem_len = res->end - res->start + 1;
- mem = request_mem_region(res->start, resource_size(res),
- fb_pdev->name);
- fbi->screen_base = ioremap(res->start, fbi->fix.smem_len);
- memset(fbi->screen_base, 0, fbi->fix.smem_len);
- */
- fb_mem_size = get_fb_size();
+ if (dev_drv->rotate_mode > X_Y_MIRROR) {
+ fb_mem_size = get_fb_size();
#if defined(CONFIG_ION_ROCKCHIP)
- if (rk_fb_alloc_buffer_by_ion(fbi, win, fb_mem_size) < 0)
- return -ENOMEM;
+ if (rk_fb_alloc_buffer_by_ion(fbi, win, fb_mem_size) < 0)
+ return -ENOMEM;
#else
- dma_addr_t fb_mem_phys;
- void *fb_mem_virt;
- fb_mem_virt = dma_alloc_writecombine(fbi->dev, fb_mem_size,
- &fb_mem_phys, GFP_KERNEL);
- if (!fb_mem_virt) {
- pr_err("%s: Failed to allocate framebuffer\n",
- __func__);
- return -ENOMEM;
- }
- fbi->fix.smem_len = fb_mem_size;
- fbi->fix.smem_start = fb_mem_phys;
- fbi->screen_base = fb_mem_virt;
+ fb_mem_virt = dma_alloc_writecombine(fbi->dev,
+ fb_mem_size, &fb_mem_phys, GFP_KERNEL);
+ if (!fb_mem_virt) {
+ pr_err("%s: Failed to allocate framebuffer\n",
+ __func__);
+ return -ENOMEM;
+ }
+ fbi->fix.smem_len = fb_mem_size;
+ fbi->fix.smem_start = fb_mem_phys;
+ fbi->screen_base = fb_mem_virt;
#endif
+ } else {
+ fbi->fix.smem_start = rk_fb->fb[0]->fix.smem_start;
+ fbi->fix.smem_len = rk_fb->fb[0]->fix.smem_len;
+ fbi->screen_base = rk_fb->fb[0]->screen_base;
+ }
-#else /* three buffer no need to copy */
- fbi->fix.smem_start = rk_fb->fb[0]->fix.smem_start;
- fbi->fix.smem_len = rk_fb->fb[0]->fix.smem_len;
- fbi->screen_base = rk_fb->fb[0]->screen_base;
-#endif
printk(KERN_INFO "fb%d:phy:%lx>>vir:%p>>len:0x%x\n", fb_id,
fbi->fix.smem_start, fbi->screen_base,
fbi->fix.smem_len);
return ret;
}
+#if 0
static int rk_release_fb_buffer(struct fb_info *fbi)
{
/* buffer for fb1 and fb3 are alloc by android */
return 0;
}
+#endif
static int init_lcdc_win(struct rk_lcdc_driver *dev_drv,
struct rk_lcdc_win *def_win)
screen->overscan.top = 100;
screen->overscan.right = 100;
screen->overscan.bottom = 100;
+
+ screen->x_mirror = dev_drv->rotate_mode & X_MIRROR;
+ screen->y_mirror = dev_drv->rotate_mode & Y_MIRROR;
+
dev_drv->screen0 = screen;
dev_drv->cur_screen = screen;
/* devie use one lcdc + rk61x scaler for dual display */
if (i == 0) {
init_waitqueue_head(&dev_drv->vsync_info.wait);
+ init_waitqueue_head(&dev_drv->update_regs_wait);
ret = device_create_file(fbi->dev, &dev_attr_vsync);
if (ret)
dev_err(fbi->dev,