}
}
+static int tegra_dc_find_cea_vic(const struct tegra_dc_mode *mode)
+{
+ struct fb_videomode m;
+ unsigned i;
+
+ tegra_dc_to_fb_videomode(&m, mode);
+
+ for (i = 1; i < CEA_MODEDB_SIZE; i++) {
+ const struct fb_videomode *curr = &cea_modes[i];
+ if (fb_mode_is_equal(&m, curr)) {
+ /* if either flag is set, then match is required */
+ if (m.flag & (FB_FLAG_RATIO_4_3 | FB_FLAG_RATIO_16_9)) {
+ if (m.flag & curr->flag & FB_FLAG_RATIO_4_3)
+ return i;
+ if (m.flag & curr->flag & FB_FLAG_RATIO_16_9)
+ return i;
+ } else {
+ return i;
+ }
+ }
+ }
+ return 0;
+}
+
static void tegra_dc_hdmi_setup_avi_infoframe(struct tegra_dc *dc, bool dvi)
{
struct tegra_dc_hdmi_data *hdmi = tegra_dc_get_outdata(dc);
else
tegra_dc_writel(dc, 0x00000000, DC_DISP_BORDER_COLOR);
- if (dc->mode.v_active == 480) {
- if (dc->mode.h_active == 640) {
- avi.m = HDMI_AVI_M_4_3;
- avi.vic = 1;
- } else {
- avi.m = HDMI_AVI_M_16_9;
- avi.vic = 3;
- }
- } else if (dc->mode.v_active == 576) {
- /* CEC modes 17 and 18 differ only by the pysical size of the
- * screen so we have to calculation the physical aspect
- * ratio. 4 * 10 / 3 is 13
- */
- if ((dc->out->h_size * 10) / dc->out->v_size > 14) {
- avi.m = HDMI_AVI_M_16_9;
- avi.vic = 18;
- } else {
- avi.m = HDMI_AVI_M_4_3;
- avi.vic = 17;
- }
- } else if (dc->mode.v_active == 720 ||
- (dc->mode.v_active == 1470 && dc->mode.stereo_mode)) {
- /* VIC for both 720p and 720p 3D mode */
- avi.m = HDMI_AVI_M_16_9;
- if (dc->mode.h_front_porch == 110)
- avi.vic = 4; /* 60 Hz */
- else
- avi.vic = 19; /* 50 Hz */
- } else if (dc->mode.v_active == 1080 ||
- (dc->mode.v_active == 2205 && dc->mode.stereo_mode)) {
- /* VIC for both 1080p and 1080p 3D mode */
- avi.m = HDMI_AVI_M_16_9;
- if (dc->mode.h_front_porch == 88) {
- if (dc->mode.pclk > 74250000)
- avi.vic = 16; /* 60 Hz */
- else
- avi.vic = 34; /* 30 Hz */
- } else if (dc->mode.h_front_porch == 528)
- avi.vic = 31; /* 50 Hz */
- else
- avi.vic = 32; /* 24 Hz */
- } else {
- avi.m = HDMI_AVI_M_16_9;
- avi.vic = 0;
- }
-
+ avi.vic = tegra_dc_find_cea_vic(&dc->mode);
+ avi.m = dc->mode.avi_m;
+ dev_dbg(&dc->ndev->dev, "HDMI AVI vic=%d m=%d\n", avi.vic, avi.m);
tegra_dc_hdmi_write_infopack(dc, HDMI_NV_PDISP_HDMI_AVI_INFOFRAME_HEADER,
HDMI_INFOFRAME_TYPE_AVI,
/* program HDMI registers and SOR sequencer */
+ tegra_dc_io_start(dc);
tegra_dc_writel(dc, VSYNC_H_POSITION(1), DC_DISP_DISP_TIMING_OPTIONS);
tegra_dc_writel(dc, DITHER_CONTROL_DISABLE | BASE_COLOR_SIZE888,
DC_DISP_DISP_COLOR_CONTROL);
tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
tegra_nvhdcp_set_plug(hdmi->nvhdcp, 1);
+ tegra_dc_io_end(dc);
}
static void tegra_dc_hdmi_disable(struct tegra_dc *dc)
fbmode->sync |= FB_SYNC_HOR_HIGH_ACT;
if (!(mode->flags & TEGRA_DC_MODE_FLAG_NEG_V_SYNC))
fbmode->sync |= FB_SYNC_VERT_HIGH_ACT;
+ if (mode->avi_m == TEGRA_DC_MODE_AVI_M_16_9)
+ fbmode->flag |= FB_FLAG_RATIO_16_9;
+ else if (mode->avi_m == TEGRA_DC_MODE_AVI_M_4_3)
+ fbmode->flag |= FB_FLAG_RATIO_4_3;
+
if (mode->rated_pclk >= 1000)
fbmode->pixclock = KHZ2PICOS(mode->rated_pclk / 1000);
else if (mode->pclk >= 1000)
mode.h_front_porch = fbmode->right_margin;
mode.v_front_porch = fbmode->lower_margin;
mode.stereo_mode = stereo_mode;
+ if (fbmode->flag & FB_FLAG_RATIO_16_9)
+ mode.avi_m = TEGRA_DC_MODE_AVI_M_16_9;
+ else if (fbmode->flag & FB_FLAG_RATIO_4_3)
+ mode.avi_m = TEGRA_DC_MODE_AVI_M_4_3;
+ else if (dc->out) { /* if ratio is unspecified, detect a default */
+ unsigned h_size = dc->out->h_size;
+ unsigned v_size = dc->out->v_size;
+
+ /* get aspect ratio */
+ if (h_size * 18 > v_size * 31 && h_size * 18 < v_size * 33)
+ mode.avi_m = TEGRA_DC_MODE_AVI_M_16_9;
+ if (h_size * 18 > v_size * 23 && h_size * 18 < v_size * 25)
+ mode.avi_m = TEGRA_DC_MODE_AVI_M_4_3;
+ }
+
if (dc->out->type == TEGRA_DC_OUT_HDMI) {
/* HDMI controller requires h_ref=1, v_ref=1 */
mode.h_ref_to_sync = 1;