From 00e20f436170fd58b742342b3032362f9ed476cf Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Tue, 7 Jan 2014 10:40:38 +0100 Subject: tegra: video: use modedb to specify framebuffer resolution Allow to specify framebufffer videomode using kernel command line parameters. NVIDIAs binary X driver later on picks up those settings and start X with current mode settings, if no EDID data are available. --- arch/arm/mach-tegra/include/mach/dc.h | 2 + drivers/video/tegra/dc/mode.c | 102 ++++++++++++++++- drivers/video/tegra/fb.c | 202 +++++++++++++++------------------- 3 files changed, 186 insertions(+), 120 deletions(-) diff --git a/arch/arm/mach-tegra/include/mach/dc.h b/arch/arm/mach-tegra/include/mach/dc.h index d22a58f22a60..784988223a76 100644 --- a/arch/arm/mach-tegra/include/mach/dc.h +++ b/arch/arm/mach-tegra/include/mach/dc.h @@ -550,6 +550,8 @@ bool tegra_dc_is_within_n_vsync(struct tegra_dc *dc, s64 ts); bool tegra_dc_does_vsync_separate(struct tegra_dc *dc, s64 new_ts, s64 old_ts); #endif /* !CONFIG_ANDROID */ +int tegra_dc_var_to_dc_mode(struct tegra_dc *dc, struct fb_var_screeninfo *var, + struct tegra_dc_mode *mode); int tegra_dc_set_mode(struct tegra_dc *dc, const struct tegra_dc_mode *mode); struct fb_videomode; int tegra_dc_set_fb_mode(struct tegra_dc *dc, const struct fb_videomode *fbmode, diff --git a/drivers/video/tegra/dc/mode.c b/drivers/video/tegra/dc/mode.c index 6457f9604e90..78d569825c61 100644 --- a/drivers/video/tegra/dc/mode.c +++ b/drivers/video/tegra/dc/mode.c @@ -272,6 +272,11 @@ int tegra_dc_set_mode(struct tegra_dc *dc, const struct tegra_dc_mode *mode) { memcpy(&dc->mode, mode, sizeof(dc->mode)); + dev_info(&dc->ndev->dev, "using mode %dx%d pclk=%d href=%d vref=%d ref=%p\n", + mode->h_active, mode->v_active, mode->pclk, + mode->h_ref_to_sync, mode->v_ref_to_sync, dc + ); + if (dc->out->type == TEGRA_DC_OUT_RGB) panel_sync_rate = tegra_dc_calc_refresh(mode); else if (dc->out->type == TEGRA_DC_OUT_DSI) @@ -286,9 +291,83 @@ int tegra_dc_set_mode(struct tegra_dc *dc, const struct tegra_dc_mode *mode) } EXPORT_SYMBOL(tegra_dc_set_mode); +int tegra_dc_var_to_dc_mode(struct tegra_dc *dc, struct fb_var_screeninfo *var, + struct tegra_dc_mode *mode) +{ + bool stereo_mode = false; + int err; + + if (!var->pixclock) + return -EINVAL; + + mode->pclk = PICOS2KHZ(var->pixclock) * 1000; + mode->h_sync_width = var->hsync_len; + mode->v_sync_width = var->vsync_len; + mode->h_back_porch = var->left_margin; + mode->v_back_porch = var->upper_margin; + mode->h_active = var->xres; + mode->v_active = var->yres; + mode->h_front_porch = var->right_margin; + mode->v_front_porch = var->lower_margin; + mode->stereo_mode = stereo_mode; + if (dc->out->type == TEGRA_DC_OUT_HDMI) { + /* HDMI controller requires h_ref=1, v_ref=1 */ + mode->h_ref_to_sync = 1; + mode->v_ref_to_sync = 1; + } else { + /* + * HACK: + * If v_front_porch is only 1, we would violate Constraint 5/6 + * in this case, increase front porch by 1 + */ + if (mode->v_front_porch <= 1) + mode->v_front_porch = 2; + + err = calc_ref_to_sync(mode); + if (err) { + dev_err(&dc->ndev->dev, "display timing ref_to_sync" + "calculation failed with code %d\n", err); + return -EINVAL; + } + dev_info(&dc->ndev->dev, "Calculated sync href=%d vref=%d\n", + mode->h_ref_to_sync, mode->v_ref_to_sync); + } + if (!check_ref_to_sync(mode)) { + dev_err(&dc->ndev->dev, + "display timing doesn't meet restrictions.\n"); + return -EINVAL; + } + +#ifndef CONFIG_TEGRA_HDMI_74MHZ_LIMIT + /* Double the pixel clock and update v_active only for + * frame packed mode */ + if (mode->stereo_mode) { + mode->pclk *= 2; + /* total v_active = yres*2 + activespace */ + mode->v_active = var->yres * 2 + + var->vsync_len + + var->upper_margin + + var->lower_margin; + } +#endif + + mode->flags = 0; + + if (!(var->sync & FB_SYNC_HOR_HIGH_ACT)) + mode->flags |= TEGRA_DC_MODE_FLAG_NEG_H_SYNC; + + if (!(var->sync & FB_SYNC_VERT_HIGH_ACT)) + mode->flags |= TEGRA_DC_MODE_FLAG_NEG_V_SYNC; + + return 0; +} +EXPORT_SYMBOL(tegra_dc_var_to_dc_mode); + + int tegra_dc_set_fb_mode(struct tegra_dc *dc, const struct fb_videomode *fbmode, bool stereo_mode) { + int err; struct tegra_dc_mode mode; if (!fbmode->pixclock) @@ -309,17 +388,28 @@ int tegra_dc_set_fb_mode(struct tegra_dc *dc, mode.h_ref_to_sync = 1; mode.v_ref_to_sync = 1; } else { - calc_ref_to_sync(&mode); + /* + * HACK: + * If v_front_porch is only 1, we would violate Constraint 5/6 + * in this case, increase front porch by 1 + */ + if (mode.v_front_porch <= 1) + mode.v_front_porch = 2; + + err = calc_ref_to_sync(&mode); + if (err) { + dev_err(&dc->ndev->dev, "display timing ref_to_sync" + "calculation failed with code %d\n", err); + return -EINVAL; + } + dev_info(&dc->ndev->dev, "Calculated sync href=%d vref=%d\n", + mode.h_ref_to_sync, mode.v_ref_to_sync); } if (!check_ref_to_sync(&mode)) { dev_err(&dc->ndev->dev, - "Display timing doesn't meet restrictions.\n"); + "display timing doesn't meet restrictions.\n"); return -EINVAL; } - dev_info(&dc->ndev->dev, "Using mode %dx%d pclk=%d href=%d vref=%d\n", - mode.h_active, mode.v_active, mode.pclk, - mode.h_ref_to_sync, mode.v_ref_to_sync - ); #ifndef CONFIG_TEGRA_HDMI_74MHZ_LIMIT /* Double the pixel clock and update v_active only for diff --git a/drivers/video/tegra/fb.c b/drivers/video/tegra/fb.c index f14ffb46b2dd..cd640bda8e31 100644 --- a/drivers/video/tegra/fb.c +++ b/drivers/video/tegra/fb.c @@ -87,8 +87,35 @@ static int tegra_fb_check_var(struct fb_var_screeninfo *var, } /* Double yres_virtual to allow double buffering through pan_display */ + var->xres_virtual = var->xres; var->yres_virtual = var->yres * 2; + /* we only support RGB ordering for now */ + switch (var->bits_per_pixel) { + case 32: + case 24: + var->bits_per_pixel = 32; + var->red.offset = 0; + var->red.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->blue.offset = 16; + var->blue.length = 8; + var->transp.offset = 24; + var->transp.length = 8; + break; + case 16: + default: + var->bits_per_pixel = 16; + var->red.offset = 11; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 6; + var->blue.offset = 0; + var->blue.length = 5; + break; + } + return 0; } @@ -97,108 +124,58 @@ static int tegra_fb_set_par(struct fb_info *info) struct tegra_fb_info *tegra_fb = info->par; struct fb_var_screeninfo *var = &info->var; struct tegra_dc *dc = tegra_fb->win->dc; + int err; - if (var->bits_per_pixel) { - /* we only support RGB ordering for now */ - switch (var->bits_per_pixel) { - case 32: - var->red.offset = 0; - var->red.length = 8; - var->green.offset = 8; - var->green.length = 8; - var->blue.offset = 16; - var->blue.length = 8; - var->transp.offset = 24; - var->transp.length = 8; - tegra_fb->win->fmt = TEGRA_WIN_FMT_R8G8B8A8; - break; - case 16: - var->red.offset = 11; - var->red.length = 5; - var->green.offset = 5; - var->green.length = 6; - var->blue.offset = 0; - var->blue.length = 5; - tegra_fb->win->fmt = TEGRA_WIN_FMT_B5G6R5; - break; - - default: - return -EINVAL; - } - /* if line_length unset, then pad the stride */ - info->fix.line_length = var->xres * var->bits_per_pixel / 8; - info->fix.line_length = round_up(info->fix.line_length, - TEGRA_LINEAR_PITCH_ALIGNMENT); - tegra_fb->win->stride = info->fix.line_length; - tegra_fb->win->stride_uv = 0; - tegra_fb->win->phys_addr_u = 0; - tegra_fb->win->phys_addr_v = 0; - } - - if (var->pixclock) { - bool stereo; - unsigned old_len = 0; - struct fb_videomode m; - struct fb_videomode *old_mode = NULL; - - fb_var_to_videomode(&m, var); - -#if defined(CONFIG_MACH_APALIS_T30) || defined(CONFIG_MACH_COLIBRI_T30) - /* Hack: avoid 24 Hz mode in X resulting in no display at all */ - if (m.refresh < 50) m.refresh = 60; -#endif /* CONFIG_MACH_APALIS_T30 | CONFIG_MACH_COLIBRI_T30 */ + struct tegra_dc_mode mode; - /* Load framebuffer info with new mode details*/ - old_mode = info->mode; - old_len = info->fix.line_length; - info->mode = (struct fb_videomode *) - fb_find_nearest_mode(&m, &info->modelist); - if (!info->mode) { - dev_warn(&tegra_fb->ndev->dev, "can't match video mode\n"); - info->mode = old_mode; - return -EINVAL; - } + switch (var->bits_per_pixel) { + case 32: + tegra_fb->win->fmt = TEGRA_WIN_FMT_R8G8B8A8; + break; + case 16: + tegra_fb->win->fmt = TEGRA_WIN_FMT_B5G6R5; + break; + default: + return -EINVAL; + break; + } - /* Update fix line_length and window stride as per new mode */ - info->fix.line_length = var->xres * var->bits_per_pixel / 8; - info->fix.line_length = round_up(info->fix.line_length, - TEGRA_LINEAR_PITCH_ALIGNMENT); - tegra_fb->win->stride = info->fix.line_length; + /* if line_length unset, then pad the stride */ + info->fix.line_length = var->xres * var->bits_per_pixel / 8; + info->fix.line_length = round_up(info->fix.line_length, + TEGRA_LINEAR_PITCH_ALIGNMENT); + tegra_fb->win->stride = info->fix.line_length; + tegra_fb->win->stride_uv = 0; + tegra_fb->win->phys_addr_u = 0; + tegra_fb->win->phys_addr_v = 0; + + tegra_fb->win->w.full = dfixed_const(var->xres); + tegra_fb->win->h.full = dfixed_const(var->yres); + tegra_fb->win->out_w = var->xres; + tegra_fb->win->out_h = var->yres; + + dev_info(&tegra_fb->ndev->dev, "switching framebuffer to %dx%d\n", + var->xres, var->yres); + + err = tegra_dc_var_to_dc_mode(dc, var, &mode); + if (err) { + dev_warn(&tegra_fb->ndev->dev, "could not convert var %d\n", err); + return -EINVAL; + } - /* - * only enable stereo if the mode supports it and - * client requests it - */ - stereo = !!(var->vmode & info->mode->vmode & -#ifndef CONFIG_TEGRA_HDMI_74MHZ_LIMIT - FB_VMODE_STEREO_FRAME_PACK); -#else - FB_VMODE_STEREO_LEFT_RIGHT); -#endif + err = tegra_dc_set_mode(dc, &mode); + if (err) { + dev_warn(&tegra_fb->ndev->dev, "could not set dc mode %d\n", err); + return -EINVAL; + } - /* Configure DC with new mode */ - if (tegra_dc_set_fb_mode(dc, info->mode, stereo)) { - /* Error while configuring DC, fallback to old mode */ - dev_warn(&tegra_fb->ndev->dev, "can't configure dc with mode %ux%u\n", - info->mode->xres, info->mode->yres); - info->mode = old_mode; - info->fix.line_length = old_len; - tegra_fb->win->stride = old_len; - return -EINVAL; - } + if (dc->enabled) + tegra_dc_disable(dc); + tegra_dc_enable(dc); - /* Reflect mode chnage on DC HW */ - if (dc->enabled) - tegra_dc_disable(dc); - tegra_dc_enable(dc); + return err; - tegra_fb->win->w.full = dfixed_const(info->mode->xres); - tegra_fb->win->h.full = dfixed_const(info->mode->yres); - tegra_fb->win->out_w = info->mode->xres; - tegra_fb->win->out_h = info->mode->yres; - } - return 0; } static int tegra_fb_setcolreg(unsigned regno, unsigned red, unsigned green, @@ -600,6 +577,8 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev, unsigned long fb_phys = 0; int ret = 0; unsigned stride; + char *option = NULL; + char driver[10]; win = tegra_dc_get_window(dc, fb_data->win); if (!win) { @@ -656,6 +635,7 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev, info->var.xres_virtual = fb_data->xres; info->var.yres_virtual = fb_data->yres * 2; info->var.bits_per_pixel = fb_data->bits_per_pixel; + info->var.activate = FB_ACTIVATE_VBL; info->var.height = tegra_dc_get_out_height(dc); info->var.width = tegra_dc_get_out_width(dc); @@ -668,10 +648,24 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev, info->var.vsync_len = 0; info->var.vmode = FB_VMODE_NONINTERLACED; + sprintf(driver, "tegrafb%d", ndev->id); + fb_get_options(driver, &option); + + if (option != NULL) { + dev_info(&ndev->dev, "parsed cmd options for %s: %s\n", driver, option); + + if (!fb_find_mode(&info->var, info, + option, vesa_modes, VESA_MODEDB_SIZE, NULL, 16)) { + ret = -EINVAL; + goto err_iounmap_fb; + } + } + win->x.full = dfixed_const(0); win->y.full = dfixed_const(0); win->w.full = dfixed_const(fb_data->xres); win->h.full = dfixed_const(fb_data->yres); + /* TODO: set to output res dc */ win->out_x = 0; win->out_y = 0; @@ -704,26 +698,6 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev, tegra_dc_sync_windows(&tegra_fb->win, 1); } - if (dc->mode.pclk > 1000) { - struct tegra_dc_mode *mode = &dc->mode; - struct fb_videomode vmode; - - if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE) - info->var.pixclock = KHZ2PICOS(mode->rated_pclk / 1000); - else - info->var.pixclock = KHZ2PICOS(mode->pclk / 1000); - info->var.left_margin = mode->h_back_porch; - info->var.right_margin = mode->h_front_porch; - info->var.upper_margin = mode->v_back_porch; - info->var.lower_margin = mode->v_front_porch; - info->var.hsync_len = mode->h_sync_width; - info->var.vsync_len = mode->v_sync_width; - - /* Keep info->var consistent with info->modelist. */ - fb_var_to_videomode(&vmode, &info->var); - fb_add_videomode(&vmode, &info->modelist); - } - return tegra_fb; err_iounmap_fb: -- cgit v1.2.3 From 2d9eefa67b15a3a6fbee37d4c31282ecad216569 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Tue, 7 Jan 2014 11:23:06 +0100 Subject: tegra: video: use new modedb based settings Use new modedb based framebuffer settings by defining default_mode in the display controllers platform data. Also impelmented the fallback logic to this default_mode in case no kernel cmd line parameter was set. --- arch/arm/mach-tegra/board-apalis_t30-panel.c | 265 +---------------------- arch/arm/mach-tegra/board-colibri_t30-panel.c | 290 +++----------------------- arch/arm/mach-tegra/include/mach/dc.h | 2 + drivers/video/tegra/dc/mode.c | 4 +- drivers/video/tegra/fb.c | 42 ++-- 5 files changed, 66 insertions(+), 537 deletions(-) diff --git a/arch/arm/mach-tegra/board-apalis_t30-panel.c b/arch/arm/mach-tegra/board-apalis_t30-panel.c index cb76ca99c083..289ed2a5a6f6 100644 --- a/arch/arm/mach-tegra/board-apalis_t30-panel.c +++ b/arch/arm/mach-tegra/board-apalis_t30-panel.c @@ -211,258 +211,6 @@ static struct resource apalis_t30_disp2_resources[] = { }; #endif /* CONFIG_TEGRA_DC */ -static struct tegra_dc_mode apalis_t30_panel_modes[] = { -#ifdef TEGRA_FB_VGA - { - /* 640x480p 60hz: EIA/CEA-861-B Format 1 */ - .pclk = 25175000, /* pixclock */ - .h_ref_to_sync = 8, - .v_ref_to_sync = 2, - .h_sync_width = 96, /* hsync_len */ - .v_sync_width = 2, /* vsync_len */ - .h_back_porch = 48, /* left_margin */ - .v_back_porch = 33, /* upper_margin */ - .h_active = 640, - .v_active = 480, - .h_front_porch = 16, /* right_margin */ - .v_front_porch = 10, /* lower_margin */ - }, - { - /* 800x480@60 (e.g. EDT ET070080DH6) */ - .pclk = 32460000, - .h_ref_to_sync = 1, - .v_ref_to_sync = 1, - .h_sync_width = 64, - .v_sync_width = 3, - .h_back_porch = 128, - .v_back_porch = 22, - .h_active = 800, - .v_active = 480, - .h_front_porch = 64, - .v_front_porch = 20, - }, - { - /* 800x600@60 */ - .pclk = 39272727, - .h_sync_width = 80, - .v_sync_width = 2, - .h_back_porch = 160, - .v_back_porch = 21, - .h_active = 800, - .v_active = 600, - .h_front_porch = 16, - .v_front_porch = 1, - }, - { - /* TouchRevolution Fusion 10 aka Chunghwa Picture Tubes - CLAA101NC05 10.1 inch 1024x600 single channel LVDS panel */ - .pclk = 48000000, - .h_sync_width = 5, - .v_sync_width = 5, - .h_back_porch = 104, - .v_back_porch = 24, - .h_active = 1024, - .v_active = 600, - .h_front_porch = 43, - .v_front_porch = 20, - }, - { - /* 1024x768@60 */ - .pclk = 78800000, - .h_sync_width = 96, - .v_sync_width = 3, - .h_back_porch = 176, - .v_back_porch = 28, - .h_active = 1024, - .v_active = 768, - .h_front_porch = 16, - .v_front_porch = 1, - }, - { - /* 1024x768@75 */ - .pclk = 82000000, - .h_sync_width = 104, - .v_sync_width = 4, - .h_back_porch = 168, - .v_back_porch = 34, - .h_active = 1024, - .v_active = 768, - .h_front_porch = 64, - .v_front_porch = 3, - }, - { - /* 1280x720@60 */ - .pclk = 74250000, - .h_ref_to_sync = 1, - .v_ref_to_sync = 1, - .h_sync_width = 40, - .v_sync_width = 5, - .h_back_porch = 220, - .v_back_porch = 20, - .h_active = 1280, - .v_active = 720, - .h_front_porch = 110, - .v_front_porch = 5, -//high active sync polarities - }, - { - /* 1280x1024@60 */ - .pclk = 108000000, -// .h_ref_to_sync = 1, -// .v_ref_to_sync = 1, - .h_sync_width = 144, - .v_sync_width = 3, - .h_back_porch = 248, - .v_back_porch = 38, - .h_active = 1280, - .v_active = 1024, - .h_front_porch = 16, - .v_front_porch = 1, -//high active sync polarities - }, - { - /* 1366x768@60 */ - .pclk = 72072000, - .h_ref_to_sync = 11, - .v_ref_to_sync = 1, - .h_sync_width = 58, - .v_sync_width = 4, - .h_back_porch = 58, - .v_back_porch = 4, - .h_active = 1366, - .v_active = 768, - .h_front_porch = 58, - .v_front_porch = 4, - }, - { - /* 1600x1200@60 */ - .pclk = 162000000, -// .h_ref_to_sync = 1, -// .v_ref_to_sync = 1, - .h_sync_width = 192, - .v_sync_width = 3, - .h_back_porch = 304, - .v_back_porch = 46, - .h_active = 1600, - .v_active = 1200, - .h_front_porch = 64, - .v_front_porch = 1, -//high active sync polarities - }, - { - .pclk = 119000000, - .h_ref_to_sync = 1, - .v_ref_to_sync = 1, - .h_sync_width = 32, - .v_sync_width = 6, - .h_back_porch = 80, - .v_back_porch = 21, - .h_active = 1680, - .v_active = 1050, - .h_front_porch = 48, - .v_front_porch = 3, - }, - { - /* 1680x1050@60 */ - .pclk = 147140000, -// .h_ref_to_sync = 1, -// .v_ref_to_sync = 1, - .h_sync_width = 184, - .v_sync_width = 3, - .h_back_porch = 288, - .v_back_porch = 33, - .h_active = 1680, - .v_active = 1050, - .h_front_porch = 104, - .v_front_porch = 1, -//high active vertical sync polarity - }, -#else /* TEGRA_FB_VGA */ - { - /* LG LP156WF1 15.6 inch full HD dual channel LVDS panel */ - .pclk = 138500000, - .h_sync_width = 32, - .v_sync_width = 5, - .h_back_porch = 80, - .v_back_porch = 46, - .h_active = 1920, - .v_active = 1080, - .h_front_porch = 48, - .v_front_porch = 6, - //low active sync polarities, high pixel clock polarity - }, - { - /* 1920x1080p 59.94/60hz EIA/CEA-861-B Format 16 */ - .pclk = 148500000, - .h_ref_to_sync = 11, - .v_ref_to_sync = 1, - .h_sync_width = 44, - .v_sync_width = 5, - .h_back_porch = 148, - .v_back_porch = 36, - .h_active = 1920, - .v_active = 1080, - .h_front_porch = 88, - .v_front_porch = 4, -//high active sync polarities - }, - { - .pclk = 154000000, - .h_ref_to_sync = 11, - .v_ref_to_sync = 1, - .h_sync_width = 32, - .v_sync_width = 6, - .h_back_porch = 80, - .v_back_porch = 26, - .h_active = 1920, - .v_active = 1200, - .h_front_porch = 48, - .v_front_porch = 3, - }, - - /* portrait modes */ - - { - .pclk = 18000000, - .h_ref_to_sync = 8, - .v_ref_to_sync = 2, - .h_sync_width = 4, - .v_sync_width = 1, - .h_back_porch = 20, - .v_back_porch = 7, - .h_active = 480, - .v_active = 640, - .h_front_porch = 8, - .v_front_porch = 8, - }, - { - .pclk = 10000000, - .h_ref_to_sync = 4, - .v_ref_to_sync = 1, - .h_sync_width = 16, - .v_sync_width = 1, - .h_back_porch = 32, - .v_back_porch = 1, - .h_active = 540, - .v_active = 960, - .h_front_porch = 32, - .v_front_porch = 2, - }, - { - .pclk = 61417000, - .h_ref_to_sync = 2, - .v_ref_to_sync = 2, - .h_sync_width = 4, - .v_sync_width = 4, - .h_back_porch = 100, - .v_back_porch = 14, - .h_active = 720, - .v_active = 1280, - .h_front_porch = 4, - .v_front_porch = 4, - }, -#endif /* TEGRA_FB_VGA */ -}; #ifdef CONFIG_TEGRA_DC static struct tegra_fb_data apalis_t30_fb_data = { @@ -511,8 +259,11 @@ static struct tegra_dc_out apalis_t30_disp1_out = { .depth = 24, .dither = TEGRA_DC_ORDERED_DITHER, - .modes = apalis_t30_panel_modes, - .n_modes = ARRAY_SIZE(apalis_t30_panel_modes), +#ifdef TEGRA_FB_VGA + .default_mode = "640x480-16@60", +#else /* TEGRA_FB_VGA */ + .default_mode = "1920x1080-16@60", +#endif /* TEGRA_FB_VGA */ .out_pins = apalis_t30_dc_out_pins, .n_out_pins = ARRAY_SIZE(apalis_t30_dc_out_pins), @@ -531,6 +282,12 @@ static struct tegra_dc_out apalis_t30_disp2_out = { .max_pixclock = KHZ2PICOS(148500), +#ifdef TEGRA_FB_VGA + .default_mode = "640x480-16@60", +#else /* TEGRA_FB_VGA */ + .default_mode = "1920x1080-16@60", +#endif /* TEGRA_FB_VGA */ + .align = TEGRA_DC_ALIGN_MSB, .order = TEGRA_DC_ORDER_RED_BLUE, diff --git a/arch/arm/mach-tegra/board-colibri_t30-panel.c b/arch/arm/mach-tegra/board-colibri_t30-panel.c index bbbbbe3dddd3..cc61b83a07b2 100644 --- a/arch/arm/mach-tegra/board-colibri_t30-panel.c +++ b/arch/arm/mach-tegra/board-colibri_t30-panel.c @@ -213,277 +213,14 @@ static struct resource colibri_t30_disp2_resources[] = { .flags = IORESOURCE_MEM, }, }; -#endif /* CONFIG_TEGRA_DC */ - -static struct tegra_dc_mode colibri_t30_panel_modes[] = { -#ifdef TEGRA_FB_VGA - { - /* 640x480p 60hz: EIA/CEA-861-B Format 1 */ - .pclk = 25175000, /* pixclock */ - .h_ref_to_sync = 8, - .v_ref_to_sync = 2, - .h_sync_width = 96, /* hsync_len */ - .v_sync_width = 2, /* vsync_len */ - .h_back_porch = 48, /* left_margin */ - .v_back_porch = 33, /* upper_margin */ - .h_active = 640, - .v_active = 480, - .h_front_porch = 16, /* right_margin */ - .v_front_porch = 10, /* lower_margin */ - }, -#else /* TEGRA_FB_VGA */ - { - /* 800x480@60 (e.g. EDT ET070080DH6) */ - .pclk = 32460000, - .h_ref_to_sync = 1, - .v_ref_to_sync = 1, - .h_sync_width = 64, - .v_sync_width = 3, - .h_back_porch = 128, - .v_back_porch = 22, - .h_active = 800, - .v_active = 480, - .h_front_porch = 64, - .v_front_porch = 20, - }, - { - /* 800x600@60 */ - .pclk = 39272727, - .h_sync_width = 80, - .v_sync_width = 2, - .h_back_porch = 160, - .v_back_porch = 21, - .h_active = 800, - .v_active = 600, - .h_front_porch = 16, - .v_front_porch = 1, - }, - { - /* TouchRevolution Fusion 10 aka Chunghwa Picture Tubes - CLAA101NC05 10.1 inch 1024x600 single channel LVDS panel */ - .pclk = 48000000, - .h_sync_width = 5, - .v_sync_width = 5, - .h_back_porch = 104, - .v_back_porch = 24, - .h_active = 1024, - .v_active = 600, - .h_front_porch = 43, - .v_front_porch = 20, - }, - { - /* 1024x768@60 */ - .pclk = 78800000, - .h_sync_width = 96, - .v_sync_width = 3, - .h_back_porch = 176, - .v_back_porch = 28, - .h_active = 1024, - .v_active = 768, - .h_front_porch = 16, - .v_front_porch = 1, - }, - { - /* 1024x768@75 */ - .pclk = 82000000, - .h_sync_width = 104, - .v_sync_width = 4, - .h_back_porch = 168, - .v_back_porch = 34, - .h_active = 1024, - .v_active = 768, - .h_front_porch = 64, - .v_front_porch = 3, - }, - { - /* 1280x720@60 */ - .pclk = 74250000, - .h_ref_to_sync = 1, - .v_ref_to_sync = 1, - .h_sync_width = 40, - .v_sync_width = 5, - .h_back_porch = 220, - .v_back_porch = 20, - .h_active = 1280, - .v_active = 720, - .h_front_porch = 110, - .v_front_porch = 5, -//high active sync polarities - }, - { - /* 1280x1024@60 */ - .pclk = 108000000, -// .h_ref_to_sync = 1, -// .v_ref_to_sync = 1, - .h_sync_width = 144, - .v_sync_width = 3, - .h_back_porch = 248, - .v_back_porch = 38, - .h_active = 1280, - .v_active = 1024, - .h_front_porch = 16, - .v_front_porch = 1, -//high active sync polarities - }, - { - /* 1366x768@60 */ - .pclk = 72072000, - .h_ref_to_sync = 11, - .v_ref_to_sync = 1, - .h_sync_width = 58, - .v_sync_width = 4, - .h_back_porch = 58, - .v_back_porch = 4, - .h_active = 1366, - .v_active = 768, - .h_front_porch = 58, - .v_front_porch = 4, - }, - { - /* 1600x1200@60 */ - .pclk = 162000000, -// .h_ref_to_sync = 1, -// .v_ref_to_sync = 1, - .h_sync_width = 192, - .v_sync_width = 3, - .h_back_porch = 304, - .v_back_porch = 46, - .h_active = 1600, - .v_active = 1200, - .h_front_porch = 64, - .v_front_porch = 1, -//high active sync polarities - }, - { - .pclk = 119000000, - .h_ref_to_sync = 1, - .v_ref_to_sync = 1, - .h_sync_width = 32, - .v_sync_width = 6, - .h_back_porch = 80, - .v_back_porch = 21, - .h_active = 1680, - .v_active = 1050, - .h_front_porch = 48, - .v_front_porch = 3, - }, - { - /* 1680x1050@60 */ - .pclk = 147140000, -// .h_ref_to_sync = 1, -// .v_ref_to_sync = 1, - .h_sync_width = 184, - .v_sync_width = 3, - .h_back_porch = 288, - .v_back_porch = 33, - .h_active = 1680, - .v_active = 1050, - .h_front_porch = 104, - .v_front_porch = 1, -//high active vertical sync polarity - }, - { - /* 1920x1080p 59.94/60hz EIA/CEA-861-B Format 16 */ - .pclk = 148500000, - .h_ref_to_sync = 11, - .v_ref_to_sync = 1, - .h_sync_width = 44, - .v_sync_width = 5, - .h_back_porch = 148, - .v_back_porch = 36, - .h_active = 1920, - .v_active = 1080, - .h_front_porch = 88, - .v_front_porch = 4, -//high active sync polarities - }, - { - .pclk = 154000000, - .h_ref_to_sync = 11, - .v_ref_to_sync = 1, - .h_sync_width = 32, - .v_sync_width = 6, - .h_back_porch = 80, - .v_back_porch = 26, - .h_active = 1920, - .v_active = 1200, - .h_front_porch = 48, - .v_front_porch = 3, - }, - /* portrait modes */ - - { - .pclk = 18000000, - .h_ref_to_sync = 8, - .v_ref_to_sync = 2, - .h_sync_width = 4, - .v_sync_width = 1, - .h_back_porch = 20, - .v_back_porch = 7, - .h_active = 480, - .v_active = 640, - .h_front_porch = 8, - .v_front_porch = 8, - }, - { - .pclk = 10000000, - .h_ref_to_sync = 4, - .v_ref_to_sync = 1, - .h_sync_width = 16, - .v_sync_width = 1, - .h_back_porch = 32, - .v_back_porch = 1, - .h_active = 540, - .v_active = 960, - .h_front_porch = 32, - .v_front_porch = 2, - }, - { - .pclk = 61417000, - .h_ref_to_sync = 2, - .v_ref_to_sync = 2, - .h_sync_width = 4, - .v_sync_width = 4, - .h_back_porch = 100, - .v_back_porch = 14, - .h_active = 720, - .v_active = 1280, - .h_front_porch = 4, - .v_front_porch = 4, - }, -#endif /* TEGRA_FB_VGA */ -}; - -#ifdef CONFIG_TEGRA_DC static struct tegra_fb_data colibri_t30_fb_data = { .win = 0, -#ifdef TEGRA_FB_VGA - .xres = 640, - .yres = 480, -#else /* TEGRA_FB_VGA */ - .xres = 800, - .yres = 480, -#endif /* TEGRA_FB_VGA */ -#ifndef CONFIG_ANDROID - .bits_per_pixel = 16, -#else - .bits_per_pixel = 32, -#endif .flags = TEGRA_FB_FLIP_ON_PROBE, }; static struct tegra_fb_data colibri_t30_hdmi_fb_data = { .win = 0, -#ifndef CONFIG_ANDROID - .xres = 640, - .yres = 480, - .bits_per_pixel = 16, -#else /* CONFIG_ANDROID */ - .xres = 1920, - .yres = 1080, - .bits_per_pixel = 32, -#endif /* !CONFIG_ANDROID */ .flags = TEGRA_FB_FLIP_ON_PROBE, }; @@ -512,8 +249,20 @@ static struct tegra_dc_out colibri_t30_disp1_out = { .depth = 18, .dither = TEGRA_DC_ORDERED_DITHER, - .modes = colibri_t30_panel_modes, - .n_modes = ARRAY_SIZE(colibri_t30_panel_modes), + /* Use 32-bit depth for android builds */ +#ifdef CONFIG_ANDROID +#ifdef TEGRA_FB_VGA + .default_mode = "640x480-32@60", +#else /* TEGRA_FB_VGA */ + .default_mode = "800x480-32@60", +#endif /* TEGRA_FB_VGA */ +#else /* CONFIG_ANDROID */ +#ifdef TEGRA_FB_VGA + .default_mode = "640x480-16@60", +#else /* TEGRA_FB_VGA */ + .default_mode = "800x480-16@60", +#endif /* TEGRA_FB_VGA */ +#endif /* CONFIG_ANDROID */ .out_pins = colibri_t30_dc_out_pins, .n_out_pins = ARRAY_SIZE(colibri_t30_dc_out_pins), @@ -532,6 +281,17 @@ static struct tegra_dc_out colibri_t30_disp2_out = { .max_pixclock = KHZ2PICOS(148500), + /* Use 32-bit depth and Full HD for android builds */ +#ifdef CONFIG_ANDROID + .default_mode = "1920x1080-32@60", +#else /* CONFIG_ANDROID */ +#ifdef TEGRA_FB_VGA + .default_mode = "640x480-16@60", +#else /* TEGRA_FB_VGA */ + .default_mode = "1920x1080-16@60", +#endif /* TEGRA_FB_VGA */ +#endif /* CONFIG_ANDROID */ + .align = TEGRA_DC_ALIGN_MSB, .order = TEGRA_DC_ORDER_RED_BLUE, diff --git a/arch/arm/mach-tegra/include/mach/dc.h b/arch/arm/mach-tegra/include/mach/dc.h index 784988223a76..a86af24fb7ee 100644 --- a/arch/arm/mach-tegra/include/mach/dc.h +++ b/arch/arm/mach-tegra/include/mach/dc.h @@ -353,6 +353,8 @@ struct tegra_dc_out { unsigned depth; unsigned dither; + const char *default_mode; + struct tegra_dc_mode *modes; int n_modes; diff --git a/drivers/video/tegra/dc/mode.c b/drivers/video/tegra/dc/mode.c index 78d569825c61..6de02200e188 100644 --- a/drivers/video/tegra/dc/mode.c +++ b/drivers/video/tegra/dc/mode.c @@ -272,9 +272,9 @@ int tegra_dc_set_mode(struct tegra_dc *dc, const struct tegra_dc_mode *mode) { memcpy(&dc->mode, mode, sizeof(dc->mode)); - dev_info(&dc->ndev->dev, "using mode %dx%d pclk=%d href=%d vref=%d ref=%p\n", + dev_info(&dc->ndev->dev, "using mode %dx%d pclk=%d href=%d vref=%d\n", mode->h_active, mode->v_active, mode->pclk, - mode->h_ref_to_sync, mode->v_ref_to_sync, dc + mode->h_ref_to_sync, mode->v_ref_to_sync ); if (dc->out->type == TEGRA_DC_OUT_RGB) diff --git a/drivers/video/tegra/fb.c b/drivers/video/tegra/fb.c index cd640bda8e31..cd39a9266d3a 100644 --- a/drivers/video/tegra/fb.c +++ b/drivers/video/tegra/fb.c @@ -577,7 +577,8 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev, unsigned long fb_phys = 0; int ret = 0; unsigned stride; - char *option = NULL; + char *param_option = NULL; + const char *option = NULL; char driver[10]; win = tegra_dc_get_window(dc, fb_data->win); @@ -648,25 +649,11 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev, info->var.vsync_len = 0; info->var.vmode = FB_VMODE_NONINTERLACED; - sprintf(driver, "tegrafb%d", ndev->id); - fb_get_options(driver, &option); - - if (option != NULL) { - dev_info(&ndev->dev, "parsed cmd options for %s: %s\n", driver, option); - - if (!fb_find_mode(&info->var, info, - option, vesa_modes, VESA_MODEDB_SIZE, NULL, 16)) { - ret = -EINVAL; - goto err_iounmap_fb; - } - } - + /* window settings */ win->x.full = dfixed_const(0); win->y.full = dfixed_const(0); win->w.full = dfixed_const(fb_data->xres); win->h.full = dfixed_const(fb_data->yres); - - /* TODO: set to output res dc */ win->out_x = 0; win->out_y = 0; win->out_w = fb_data->xres; @@ -680,6 +667,29 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev, win->stride_uv = 0; win->flags = TEGRA_WIN_FLAG_ENABLED; + /* try to use kernel cmd line specified mode */ + sprintf(driver, "tegrafb%d", ndev->id); + fb_get_options(driver, ¶m_option); + if (param_option != NULL) { + option = param_option; + dev_info(&ndev->dev, "parse cmd options for %s: %s\n", + driver, option); + } else { + option = dc->out->default_mode; + dev_info(&ndev->dev, "use default mode for %s: %s\n", + driver, option); + } + + if (option != NULL) + { + if (!fb_find_mode(&info->var, info, option, + vesa_modes, VESA_MODEDB_SIZE, NULL, 16)) { + ret = -EINVAL; + goto err_iounmap_fb; + } + } + + /* activate current settings.. */ if (fb_mem) tegra_fb_set_par(info); -- cgit v1.2.3 From e6f686ef0b4668caa6d60e02cce650d99c571a4d Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Tue, 7 Jan 2014 13:32:44 +0100 Subject: tegra: video: use correct return value for callback --- arch/arm/mach-tegra/include/mach/dc.h | 2 +- drivers/video/tegra/dc/ext/dev.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-tegra/include/mach/dc.h b/arch/arm/mach-tegra/include/mach/dc.h index a86af24fb7ee..abab990aab23 100644 --- a/arch/arm/mach-tegra/include/mach/dc.h +++ b/arch/arm/mach-tegra/include/mach/dc.h @@ -598,7 +598,7 @@ struct tegra_dc_edid { struct tegra_dc_edid *tegra_dc_get_edid(struct tegra_dc *dc); void tegra_dc_put_edid(struct tegra_dc_edid *edid); -int tegra_dc_set_flip_callback(void (*callback)(void)); +int tegra_dc_set_flip_callback(int (*callback)(void)); int tegra_dc_unset_flip_callback(void); int tegra_dc_get_panel_sync_rate(void); diff --git a/drivers/video/tegra/dc/ext/dev.c b/drivers/video/tegra/dc/ext/dev.c index c8104deb5ed6..37a6d9bd3f80 100644 --- a/drivers/video/tegra/dc/ext/dev.c +++ b/drivers/video/tegra/dc/ext/dev.c @@ -296,7 +296,7 @@ static int tegra_dc_ext_set_windowattr(struct tegra_dc_ext *ext, #endif /* !CONFIG_ANDROID */ } -static void (*flip_callback)(void); +static int (*flip_callback)(void); static spinlock_t flip_callback_lock; static bool init_tegra_dc_flip_callback_called; @@ -309,7 +309,7 @@ static int __init init_tegra_dc_flip_callback(void) pure_initcall(init_tegra_dc_flip_callback); -int tegra_dc_set_flip_callback(void (*callback)(void)) +int tegra_dc_set_flip_callback(int (*callback)(void)) { WARN_ON(!init_tegra_dc_flip_callback_called); -- cgit v1.2.3 From 940e4718d4367ff516e1a4fa8c0fa32b46097298 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Tue, 7 Jan 2014 13:35:39 +0100 Subject: tegra: video: remove unreferenced resolution from tegra_fb_info --- drivers/video/tegra/fb.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/video/tegra/fb.c b/drivers/video/tegra/fb.c index cd39a9266d3a..575f85ad9653 100644 --- a/drivers/video/tegra/fb.c +++ b/drivers/video/tegra/fb.c @@ -55,9 +55,6 @@ struct tegra_fb_info { bool valid; struct resource *fb_mem; - - int xres; - int yres; }; /* palette array used by the fbcon */ @@ -598,8 +595,6 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev, tegra_fb->win = win; tegra_fb->ndev = ndev; tegra_fb->fb_mem = fb_mem; - tegra_fb->xres = fb_data->xres; - tegra_fb->yres = fb_data->yres; if (fb_mem) { fb_size = resource_size(fb_mem); -- cgit v1.2.3 From c54b9b8f76bfd8786c6cfbce942c1b1aebcb3ef1 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Thu, 9 Jan 2014 13:20:53 +0100 Subject: tegra: video: parse multiple modedbs In order to find a viable resolution we not only parse VESA mode, we also parse CEA (multimedia) modes and our own small modedb (for specific touch screens). --- arch/arm/mach-tegra/include/mach/dc.h | 3 +- drivers/video/tegra/dc/mode.c | 78 +++++++++++++++++++++++++++++++++++ drivers/video/tegra/fb.c | 7 +++- 3 files changed, 85 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-tegra/include/mach/dc.h b/arch/arm/mach-tegra/include/mach/dc.h index abab990aab23..13dc8c0be03a 100644 --- a/arch/arm/mach-tegra/include/mach/dc.h +++ b/arch/arm/mach-tegra/include/mach/dc.h @@ -601,5 +601,6 @@ void tegra_dc_put_edid(struct tegra_dc_edid *edid); int tegra_dc_set_flip_callback(int (*callback)(void)); int tegra_dc_unset_flip_callback(void); int tegra_dc_get_panel_sync_rate(void); - +int tegra_fb_find_mode(struct fb_var_screeninfo *var, struct fb_info *info, + const char* option, unsigned int default_bpp); #endif diff --git a/drivers/video/tegra/dc/mode.c b/drivers/video/tegra/dc/mode.c index 6de02200e188..0a0e730ad174 100644 --- a/drivers/video/tegra/dc/mode.c +++ b/drivers/video/tegra/dc/mode.c @@ -26,6 +26,84 @@ #include "dc_reg.h" #include "dc_priv.h" +const struct fb_videomode tegra_modes[] = { + /* TouchRevolution Fusion 10" aka Chunghwa Picture Tubes + * CLAA100NC05 10.1 inch 1024x600 single channel LVDS panel + */ + { + .name = "1024x600", .refresh = 60, .xres = 1024, .yres = 600, + .pixclock = 20833, .left_margin = 104, .right_margin = 43, + .upper_margin = 24, .lower_margin = 20, + .hsync_len = 5, .vsync_len = 5, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .flag = FB_FLAG_RATIO_16_9, + .vmode = FB_VMODE_NONINTERLACED + }, + /* EDT 5.7" ET070080DH or TouchRevolution Fusion 7" */ + { + .name = "800x480", .refresh = 60, .xres = 800, .yres = 480, + .pixclock = 30807, .left_margin = 128, .right_margin = 64, + .upper_margin = 22, .lower_margin = 20, + .hsync_len = 64, .vsync_len = 3, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .flag = FB_FLAG_RATIO_16_9, + .vmode = FB_VMODE_NONINTERLACED + }, + /* Portrait modes */ + { + .name = "480x640", .refresh = 60, .xres = 480, .yres = 640, + .pixclock = 55555, .left_margin = 20, .right_margin = 8, + .upper_margin = 7, .lower_margin = 8, + .hsync_len = 4, .vsync_len = 1, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .vmode = FB_VMODE_NONINTERLACED + }, + { + .name = "540x960", .refresh = 60, .xres = 540, .yres = 960, + .pixclock = 100000, .left_margin = 32, .right_margin = 32, + .upper_margin = 1, .lower_margin = 2, + .hsync_len = 16, .vsync_len = 1, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .vmode = FB_VMODE_NONINTERLACED + }, + { + .name = "720x1280", .refresh = 60, .xres = 720, .yres = 1280, + .pixclock = 16282, .left_margin = 100, .right_margin = 4, + .upper_margin = 14, .lower_margin = 4, + .hsync_len = 4, .vsync_len = 4, + .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + .vmode = FB_VMODE_NONINTERLACED + }, +}; + +/* try to find best matching mode using our modes, VESA and CEA modes from + * modedb + */ +int tegra_fb_find_mode(struct fb_var_screeninfo *var, struct fb_info *info, + const char* option, unsigned int default_bpp) +{ + int out; + + out = fb_find_mode(var, info, option, tegra_modes, + ARRAY_SIZE(tegra_modes), NULL, default_bpp); + + /* Only accept this mode if we found a reasonable match (resolution) */ + if (out == 1 || out == 2) + return out; + + out = fb_find_mode(&info->var, info, option, + cea_modes, CEA_MODEDB_SIZE, NULL, default_bpp); + + /* Check if we found a full match */ + if (out == 1 || out == 2) + return out; + + return fb_find_mode(&info->var, info, option, + vesa_modes, VESA_MODEDB_SIZE, NULL, default_bpp); +} +EXPORT_SYMBOL(tegra_fb_find_mode); + + /* return non-zero if constraint is violated */ static int calc_h_ref_to_sync(const struct tegra_dc_mode *mode, int *href) { diff --git a/drivers/video/tegra/fb.c b/drivers/video/tegra/fb.c index 575f85ad9653..90d1363ecf9c 100644 --- a/drivers/video/tegra/fb.c +++ b/drivers/video/tegra/fb.c @@ -677,8 +677,11 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev, if (option != NULL) { - if (!fb_find_mode(&info->var, info, option, - vesa_modes, VESA_MODEDB_SIZE, NULL, 16)) { + if (!strcmp(option, "off")) { + ret = -ENODEV; + goto err_iounmap_fb; + } + if (!tegra_fb_find_mode(&info->var, info, option, 16)) { ret = -EINVAL; goto err_iounmap_fb; } -- cgit v1.2.3 From 3d8f44c100f23574e9a4a9c74fa6054e48ca53c2 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Mon, 13 Jan 2014 12:32:29 +0100 Subject: colibri_t20: video: use new modedb based settings Use modedb to set mode on framebuffer/display controller for Tegra 20 based module Colibri T20 too. --- arch/arm/mach-tegra/board-colibri_t20-panel.c | 278 ++------------------------ 1 file changed, 21 insertions(+), 257 deletions(-) diff --git a/arch/arm/mach-tegra/board-colibri_t20-panel.c b/arch/arm/mach-tegra/board-colibri_t20-panel.c index 6c6ff73eb318..8d8b9e74c58c 100644 --- a/arch/arm/mach-tegra/board-colibri_t20-panel.c +++ b/arch/arm/mach-tegra/board-colibri_t20-panel.c @@ -208,268 +208,13 @@ static struct resource colibri_t20_disp2_resources[] = { }, }; -static struct tegra_dc_mode colibri_t20_panel_modes[] = { -#ifdef TEGRA_FB_VGA - { - /* 640x480p 60hz: EIA/CEA-861-B Format 1 */ - .pclk = 25175000, /* pixclock */ - .h_ref_to_sync = 8, - .v_ref_to_sync = 2, - .h_sync_width = 96, /* hsync_len */ - .v_sync_width = 2, /* vsync_len */ - .h_back_porch = 48, /* left_margin */ - .v_back_porch = 33, /* upper_margin */ - .h_active = 640, - .v_active = 480, - .h_front_porch = 16, /* right_margin */ - .v_front_porch = 10, /* lower_margin */ - }, -#else /* TEGRA_FB_VGA */ - { - /* 800x480@60 (e.g. EDT ET070080DH6) */ - .pclk = 32460000, - .h_ref_to_sync = 1, - .v_ref_to_sync = 1, - .h_sync_width = 64, - .v_sync_width = 3, - .h_back_porch = 128, - .v_back_porch = 22, - .h_active = 800, - .v_active = 480, - .h_front_porch = 64, - .v_front_porch = 20, - }, - { - /* 800x600@60 */ - .pclk = 39272727, - .h_sync_width = 80, - .v_sync_width = 2, - .h_back_porch = 160, - .v_back_porch = 21, - .h_active = 800, - .v_active = 600, - .h_front_porch = 16, - .v_front_porch = 1, - }, - { - /* TouchRevolution Fusion 10 aka Chunghwa Picture Tubes - CLAA101NC05 10.1 inch 1024x600 single channel LVDS panel */ - .pclk = 48000000, - .h_sync_width = 5, - .v_sync_width = 5, - .h_back_porch = 104, - .v_back_porch = 24, - .h_active = 1024, - .v_active = 600, - .h_front_porch = 43, - .v_front_porch = 20, - }, - { - /* 1024x768@60 */ -//pll_c 76Hz - .pclk = 78800000, - .h_sync_width = 96, - .v_sync_width = 3, - .h_back_porch = 176, - .v_back_porch = 28, - .h_active = 1024, - .v_active = 768, - .h_front_porch = 16, - .v_front_porch = 1, - }, - { - /* 1024x768@75 */ - .pclk = 82000000, - .h_sync_width = 104, - .v_sync_width = 4, - .h_back_porch = 168, - .v_back_porch = 34, - .h_active = 1024, - .v_active = 768, - .h_front_porch = 64, - .v_front_porch = 3, - }, - { - /* 1280x720@70 */ - .pclk = 86400000, - .h_ref_to_sync = 1, - .v_ref_to_sync = 1, - .h_sync_width = 40, - .v_sync_width = 5, - .h_back_porch = 220, - .v_back_porch = 20, - .h_active = 1280, - .v_active = 720, - .h_front_porch = 110, - .v_front_porch = 5, -//high active sync polarities - }, - { - /* 1280x1024@60 */ - .pclk = 108000000, -// .h_ref_to_sync = 1, -// .v_ref_to_sync = 1, - .h_sync_width = 144, - .v_sync_width = 3, - .h_back_porch = 248, - .v_back_porch = 38, - .h_active = 1280, - .v_active = 1024, - .h_front_porch = 16, - .v_front_porch = 1, -//high active sync polarities - }, - { - /* 1366x768@60 */ - .pclk = 72072000, - .h_ref_to_sync = 11, - .v_ref_to_sync = 1, - .h_sync_width = 58, - .v_sync_width = 4, - .h_back_porch = 58, - .v_back_porch = 4, - .h_active = 1366, - .v_active = 768, - .h_front_porch = 58, - .v_front_porch = 4, - }, - { - /* 1600x1200@60 */ - .pclk = 144000000, -//[ 1.423072] tegradc tegradc.0: can't divide 216000000 clock to 162000000 -1/+9% 144000000 160380000 176580000 -// .pclk = 162000000, -// .h_ref_to_sync = 1, -// .v_ref_to_sync = 1, - .h_sync_width = 192, - .v_sync_width = 3, - .h_back_porch = 304, - .v_back_porch = 46, - .h_active = 1600, - .v_active = 1200, - .h_front_porch = 64, - .v_front_porch = 1, -//high active sync polarities - }, - { - /* 1680x1050@60 */ - .pclk = 144000000, -//[ 1.423139] tegradc tegradc.0: can't divide 216000000 clock to 147140000 -1/+9% 144000000 145668600 160382600 -// .pclk = 147140000, -// .h_ref_to_sync = 1, -// .v_ref_to_sync = 1, - .h_sync_width = 184, - .v_sync_width = 3, - .h_back_porch = 288, - .v_back_porch = 33, - .h_active = 1680, - .v_active = 1050, - .h_front_porch = 104, - .v_front_porch = 1, -//high active vertical sync polarity - }, - { - /* 1920x1080p 59.94/60hz EIA/CEA-861-B Format 16 */ - .pclk = 144000000, -//[ 3.361002] tegradc tegradc.0: can't divide 216000000 clock to 148500000 -1/+9% 144000000 147015000 161865000 -// .pclk = 148500000, - .h_ref_to_sync = 11, - .v_ref_to_sync = 1, - .h_sync_width = 44, - .v_sync_width = 5, - .h_back_porch = 148, - .v_back_porch = 36, - .h_active = 1920, - .v_active = 1080, - .h_front_porch = 88, - .v_front_porch = 4, -//high active sync polarities - }, - { - .pclk = 144000000, -//[ 3.371657] tegradc tegradc.0: can't divide 216000000 clock to 154000000 -1/+9% 144000000 152460000 167860000 -// .pclk = 154000000, - .h_ref_to_sync = 11, - .v_ref_to_sync = 1, - .h_sync_width = 32, - .v_sync_width = 6, - .h_back_porch = 80, - .v_back_porch = 26, - .h_active = 1920, - .v_active = 1200, - .h_front_porch = 48, - .v_front_porch = 3, - }, - - /* portrait modes */ - - { - .pclk = 18000000, - .h_ref_to_sync = 8, - .v_ref_to_sync = 2, - .h_sync_width = 4, - .v_sync_width = 1, - .h_back_porch = 20, - .v_back_porch = 7, - .h_active = 480, - .v_active = 640, - .h_front_porch = 8, - .v_front_porch = 8, - }, - { - .pclk = 10000000, - .h_ref_to_sync = 4, - .v_ref_to_sync = 1, - .h_sync_width = 16, - .v_sync_width = 1, - .h_back_porch = 32, - .v_back_porch = 1, - .h_active = 540, - .v_active = 960, - .h_front_porch = 32, - .v_front_porch = 2, - }, - { - .pclk = 61417000, - .h_ref_to_sync = 2, - .v_ref_to_sync = 2, - .h_sync_width = 4, - .v_sync_width = 4, - .h_back_porch = 100, - .v_back_porch = 14, - .h_active = 720, - .v_active = 1280, - .h_front_porch = 4, - .v_front_porch = 4, - }, -#endif /* TEGRA_FB_VGA */ -}; - static struct tegra_fb_data colibri_t20_fb_data = { .win = 0, -#ifdef TEGRA_FB_VGA - .xres = 640, - .yres = 480, -#else /* TEGRA_FB_VGA */ - .xres = 800, - .yres = 480, -#endif /* TEGRA_FB_VGA */ -#ifndef CONFIG_ANDROID - .bits_per_pixel = 16, -#else - .bits_per_pixel = 32, -#endif .flags = TEGRA_FB_FLIP_ON_PROBE, }; static struct tegra_fb_data colibri_t20_hdmi_fb_data = { .win = 0, - .xres = 640, - .yres = 480, -#ifndef CONFIG_ANDROID - .bits_per_pixel = 16, -#else - .bits_per_pixel = 32, -#endif .flags = TEGRA_FB_FLIP_ON_PROBE, }; @@ -499,8 +244,20 @@ static struct tegra_dc_out colibri_t20_disp1_out = { .depth = 18, .dither = TEGRA_DC_ORDERED_DITHER, - .modes = colibri_t20_panel_modes, - .n_modes = ARRAY_SIZE(colibri_t20_panel_modes), + /* Use 32-bit depth for android builds */ +#ifdef CONFIG_ANDROID +#ifdef TEGRA_FB_VGA + .default_mode = "640x480-32@60", +#else /* TEGRA_FB_VGA */ + .default_mode = "800x480-32@60", +#endif /* TEGRA_FB_VGA */ +#else /* CONFIG_ANDROID */ +#ifdef TEGRA_FB_VGA + .default_mode = "640x480-16@60", +#else /* TEGRA_FB_VGA */ + .default_mode = "800x480-16@60", +#endif /* TEGRA_FB_VGA */ +#endif /* CONFIG_ANDROID */ .out_pins = colibri_t20_dc_out_pins, .n_out_pins = ARRAY_SIZE(colibri_t20_dc_out_pins), @@ -518,6 +275,13 @@ static struct tegra_dc_out colibri_t20_disp2_out = { .max_pixclock = KHZ2PICOS(148500), + /* Use 32-bit depth for android builds */ +#ifdef CONFIG_ANDROID + .default_mode = "640x480-32@60", +#else /* CONFIG_ANDROID */ + .default_mode = "640x480-16@60", +#endif /* CONFIG_ANDROID */ + .align = TEGRA_DC_ALIGN_MSB, .order = TEGRA_DC_ORDER_RED_BLUE, -- cgit v1.2.3 From f939885e6f77ac92bad278487ccf651f2256a7b0 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 22 Jan 2014 18:09:13 +0100 Subject: video: tegra: updated comments, move front_porch work around Updated several comments to make code easier to read and understand. Also use the front_porch workaround in any case, for HDMI output too. --- drivers/video/tegra/dc/mode.c | 24 +++++++++++++++--------- drivers/video/tegra/fb.c | 15 +++++++++++++-- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/drivers/video/tegra/dc/mode.c b/drivers/video/tegra/dc/mode.c index 0a0e730ad174..be0d2bc5f035 100644 --- a/drivers/video/tegra/dc/mode.c +++ b/drivers/video/tegra/dc/mode.c @@ -388,19 +388,22 @@ int tegra_dc_var_to_dc_mode(struct tegra_dc *dc, struct fb_var_screeninfo *var, mode->h_front_porch = var->right_margin; mode->v_front_porch = var->lower_margin; mode->stereo_mode = stereo_mode; + + /* + * HACK: + * If v_front_porch is only 1, we would violate Constraint 5/6 + * in this case, increase front porch by 1 + */ + if (mode->v_front_porch <= 1) + mode->v_front_porch = 2; + + if (dc->out->type == TEGRA_DC_OUT_HDMI) { /* HDMI controller requires h_ref=1, v_ref=1 */ mode->h_ref_to_sync = 1; mode->v_ref_to_sync = 1; } else { - /* - * HACK: - * If v_front_porch is only 1, we would violate Constraint 5/6 - * in this case, increase front porch by 1 - */ - if (mode->v_front_porch <= 1) - mode->v_front_porch = 2; - + /* Calculate ref_to_sync signals */ err = calc_ref_to_sync(mode); if (err) { dev_err(&dc->ndev->dev, "display timing ref_to_sync" @@ -441,7 +444,10 @@ int tegra_dc_var_to_dc_mode(struct tegra_dc *dc, struct fb_var_screeninfo *var, } EXPORT_SYMBOL(tegra_dc_var_to_dc_mode); - +/* + * This method is only used by sysfs interface + * /sys/devices/tegradc.1/nvdps + */ int tegra_dc_set_fb_mode(struct tegra_dc *dc, const struct fb_videomode *fbmode, bool stereo_mode) { diff --git a/drivers/video/tegra/fb.c b/drivers/video/tegra/fb.c index 90d1363ecf9c..70b82bde9e43 100644 --- a/drivers/video/tegra/fb.c +++ b/drivers/video/tegra/fb.c @@ -125,7 +125,9 @@ static int tegra_fb_set_par(struct fb_info *info) struct tegra_dc_mode mode; - + /* This is usually altered to 16/32 by tegra_fb_check_var + * above which is called before this function + */ switch (var->bits_per_pixel) { case 32: tegra_fb->win->fmt = TEGRA_WIN_FMT_R8G8B8A8; @@ -167,6 +169,7 @@ static int tegra_fb_set_par(struct fb_info *info) return -EINVAL; } + /* Reflect changes on HW */ if (dc->enabled) tegra_dc_disable(dc); tegra_dc_enable(dc); @@ -678,6 +681,12 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev, if (option != NULL) { if (!strcmp(option, "off")) { + /* This off option works perfectly for framebuffer + * device, however the tegra binary driver somehow + * has troubles to handle a missing fb0 when there + * (then, dc1 gets remapped to fb0, which seems + * to be an issue for the binary driver)... + */ ret = -ENODEV; goto err_iounmap_fb; } @@ -687,7 +696,9 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev, } } - /* activate current settings.. */ + /* Activate current settings (tegra_fb_find_mode has call + * tegra_fb_check_var already) + */ if (fb_mem) tegra_fb_set_par(info); -- cgit v1.2.3 From 009e6229134cffa05aafb780362b7c5480ec7a16 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 22 Jan 2014 18:23:26 +0100 Subject: colibri_t20/colibri_t30/apalis_t30: remove TEGRA_FB_VGA defines Remove TEGRA_FB_VGA defines and use VGA as default. Since initial mode is now configureable through kernel cmd line parameter, we don't need those compile time helpers. --- arch/arm/mach-tegra/board-apalis_t30-panel.c | 19 ------------------- arch/arm/mach-tegra/board-apalis_t30.h | 3 --- arch/arm/mach-tegra/board-colibri_t20-panel.c | 8 -------- arch/arm/mach-tegra/board-colibri_t20.h | 3 --- arch/arm/mach-tegra/board-colibri_t30-panel.c | 12 ------------ arch/arm/mach-tegra/board-colibri_t30.h | 3 --- 6 files changed, 48 deletions(-) diff --git a/arch/arm/mach-tegra/board-apalis_t30-panel.c b/arch/arm/mach-tegra/board-apalis_t30-panel.c index 289ed2a5a6f6..1be339dce6ef 100644 --- a/arch/arm/mach-tegra/board-apalis_t30-panel.c +++ b/arch/arm/mach-tegra/board-apalis_t30-panel.c @@ -215,22 +215,11 @@ static struct resource apalis_t30_disp2_resources[] = { #ifdef CONFIG_TEGRA_DC static struct tegra_fb_data apalis_t30_fb_data = { .win = 0, -#ifdef TEGRA_FB_VGA - .xres = 640, - .yres = 480, -#else /* TEGRA_FB_VGA */ - .xres = 1920, - .yres = 1080, -#endif /* TEGRA_FB_VGA */ - .bits_per_pixel = 16, .flags = TEGRA_FB_FLIP_ON_PROBE, }; static struct tegra_fb_data apalis_t30_hdmi_fb_data = { .win = 0, - .xres = 640, - .yres = 480, - .bits_per_pixel = 16, .flags = TEGRA_FB_FLIP_ON_PROBE, }; @@ -259,11 +248,7 @@ static struct tegra_dc_out apalis_t30_disp1_out = { .depth = 24, .dither = TEGRA_DC_ORDERED_DITHER, -#ifdef TEGRA_FB_VGA .default_mode = "640x480-16@60", -#else /* TEGRA_FB_VGA */ - .default_mode = "1920x1080-16@60", -#endif /* TEGRA_FB_VGA */ .out_pins = apalis_t30_dc_out_pins, .n_out_pins = ARRAY_SIZE(apalis_t30_dc_out_pins), @@ -282,11 +267,7 @@ static struct tegra_dc_out apalis_t30_disp2_out = { .max_pixclock = KHZ2PICOS(148500), -#ifdef TEGRA_FB_VGA .default_mode = "640x480-16@60", -#else /* TEGRA_FB_VGA */ - .default_mode = "1920x1080-16@60", -#endif /* TEGRA_FB_VGA */ .align = TEGRA_DC_ALIGN_MSB, .order = TEGRA_DC_ORDER_RED_BLUE, diff --git a/arch/arm/mach-tegra/board-apalis_t30.h b/arch/arm/mach-tegra/board-apalis_t30.h index 8c11647b8319..9fde9ef1d89e 100644 --- a/arch/arm/mach-tegra/board-apalis_t30.h +++ b/arch/arm/mach-tegra/board-apalis_t30.h @@ -26,9 +26,6 @@ #include #include -/* Run framebuffer in VGA mode */ -//#define TEGRA_FB_VGA - /* GPIO */ #define APALIS_GPIO1 TEGRA_GPIO_PS2 diff --git a/arch/arm/mach-tegra/board-colibri_t20-panel.c b/arch/arm/mach-tegra/board-colibri_t20-panel.c index 8d8b9e74c58c..c4746590d209 100644 --- a/arch/arm/mach-tegra/board-colibri_t20-panel.c +++ b/arch/arm/mach-tegra/board-colibri_t20-panel.c @@ -246,17 +246,9 @@ static struct tegra_dc_out colibri_t20_disp1_out = { /* Use 32-bit depth for android builds */ #ifdef CONFIG_ANDROID -#ifdef TEGRA_FB_VGA .default_mode = "640x480-32@60", -#else /* TEGRA_FB_VGA */ - .default_mode = "800x480-32@60", -#endif /* TEGRA_FB_VGA */ #else /* CONFIG_ANDROID */ -#ifdef TEGRA_FB_VGA .default_mode = "640x480-16@60", -#else /* TEGRA_FB_VGA */ - .default_mode = "800x480-16@60", -#endif /* TEGRA_FB_VGA */ #endif /* CONFIG_ANDROID */ .out_pins = colibri_t20_dc_out_pins, diff --git a/arch/arm/mach-tegra/board-colibri_t20.h b/arch/arm/mach-tegra/board-colibri_t20.h index c7f2c5dcad33..23e9cdbda749 100644 --- a/arch/arm/mach-tegra/board-colibri_t20.h +++ b/arch/arm/mach-tegra/board-colibri_t20.h @@ -23,9 +23,6 @@ #define COLIBRI_T20_VI #endif -/* Run framebuffer in VGA mode */ -#define TEGRA_FB_VGA - /* Uncomment to activate 32-bit GMI address/databus */ //#define GMI_32BIT diff --git a/arch/arm/mach-tegra/board-colibri_t30-panel.c b/arch/arm/mach-tegra/board-colibri_t30-panel.c index cc61b83a07b2..14c711039f41 100644 --- a/arch/arm/mach-tegra/board-colibri_t30-panel.c +++ b/arch/arm/mach-tegra/board-colibri_t30-panel.c @@ -251,17 +251,9 @@ static struct tegra_dc_out colibri_t30_disp1_out = { /* Use 32-bit depth for android builds */ #ifdef CONFIG_ANDROID -#ifdef TEGRA_FB_VGA .default_mode = "640x480-32@60", -#else /* TEGRA_FB_VGA */ - .default_mode = "800x480-32@60", -#endif /* TEGRA_FB_VGA */ #else /* CONFIG_ANDROID */ -#ifdef TEGRA_FB_VGA .default_mode = "640x480-16@60", -#else /* TEGRA_FB_VGA */ - .default_mode = "800x480-16@60", -#endif /* TEGRA_FB_VGA */ #endif /* CONFIG_ANDROID */ .out_pins = colibri_t30_dc_out_pins, @@ -285,11 +277,7 @@ static struct tegra_dc_out colibri_t30_disp2_out = { #ifdef CONFIG_ANDROID .default_mode = "1920x1080-32@60", #else /* CONFIG_ANDROID */ -#ifdef TEGRA_FB_VGA .default_mode = "640x480-16@60", -#else /* TEGRA_FB_VGA */ - .default_mode = "1920x1080-16@60", -#endif /* TEGRA_FB_VGA */ #endif /* CONFIG_ANDROID */ .align = TEGRA_DC_ALIGN_MSB, diff --git a/arch/arm/mach-tegra/board-colibri_t30.h b/arch/arm/mach-tegra/board-colibri_t30.h index 21de318173ea..85563fe222ba 100644 --- a/arch/arm/mach-tegra/board-colibri_t30.h +++ b/arch/arm/mach-tegra/board-colibri_t30.h @@ -32,9 +32,6 @@ #define COLIBRI_T30_VI #endif -/* Run framebuffer in VGA mode */ -#define TEGRA_FB_VGA - /* GPIO */ #define DDC_SCL TEGRA_GPIO_PV4 /* X2-15 */ -- cgit v1.2.3