void mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on) { struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); struct mdfld_dsi_dpi_output *dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder); struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder); int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder); struct drm_device *dev = dsi_config->dev; struct drm_psb_private *dev_priv = dev->dev_private; u32 mipi_reg = MIPI; u32 pipeconf_reg = PIPEACONF; if(pipe) { mipi_reg = MIPI_C; pipeconf_reg = PIPECCONF; } /* Start up display island if it was shutdown */ if (!gma_power_begin(dev, true)) return; if(on) { if (mdfld_get_panel_type(dev, pipe) == TMD_VID){ mdfld_dsi_dpi_turn_on(dpi_output, pipe); } else { /* Enable mipi port */ REG_WRITE(mipi_reg, (REG_READ(mipi_reg) | (1 << 31))); REG_READ(mipi_reg); mdfld_dsi_dpi_turn_on(dpi_output, pipe); mdfld_dsi_tpo_ic_init(dsi_config, pipe); } if(pipe == 2) { dev_priv->dpi_panel_on2 = true; } else { dev_priv->dpi_panel_on = true; } } else { if (mdfld_get_panel_type(dev, pipe) == TMD_VID) { mdfld_dsi_dpi_shut_down(dpi_output, pipe); } else { mdfld_dsi_dpi_shut_down(dpi_output, pipe); /* Disable mipi port */ REG_WRITE(mipi_reg, (REG_READ(mipi_reg) & ~(1<<31))); REG_READ(mipi_reg); } if(pipe == 2) dev_priv->dpi_panel_on2 = false; else dev_priv->dpi_panel_on = false; } gma_power_end(dev); }
void mdfld_output_init(struct drm_device *dev) { int type; /* MIPI panel 1 */ type = mdfld_get_panel_type(dev, 0); dev_info(dev->dev, "panel 1: type is %d\n", type); init_panel(dev, 0, type); /* MIPI panel 2 */ type = mdfld_get_panel_type(dev, 2); dev_info(dev->dev, "panel 2: type is %d\n", type); init_panel(dev, 2, type); }
static void mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on) { struct mdfld_dsi_encoder *dsi_encoder = mdfld_dsi_encoder(encoder); struct mdfld_dsi_dpi_output *dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder); struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder); int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder); struct drm_device *dev = dsi_config->dev; struct drm_psb_private *dev_priv = dev->dev_private; /*start up display island if it was shutdown*/ if (!gma_power_begin(dev, true)) return; if (on) { if (mdfld_get_panel_type(dev, pipe) == TMD_VID) mdfld_dsi_dpi_turn_on(dpi_output, pipe); else if (mdfld_get_panel_type(dev, pipe) == TC35876X) mdfld_dsi_configure_up(dsi_encoder, pipe); else { /*enable mipi port*/ REG_WRITE(MIPI_PORT_CONTROL(pipe), REG_READ(MIPI_PORT_CONTROL(pipe)) | BIT(31)); REG_READ(MIPI_PORT_CONTROL(pipe)); mdfld_dsi_dpi_turn_on(dpi_output, pipe); mdfld_dsi_tpo_ic_init(dsi_config, pipe); } dev_priv->dpi_panel_on[pipe] = true; } else { if (mdfld_get_panel_type(dev, pipe) == TMD_VID) mdfld_dsi_dpi_shut_down(dpi_output, pipe); else if (mdfld_get_panel_type(dev, pipe) == TC35876X) mdfld_dsi_configure_down(dsi_encoder, pipe); else { mdfld_dsi_dpi_shut_down(dpi_output, pipe); /*disable mipi port*/ REG_WRITE(MIPI_PORT_CONTROL(pipe), REG_READ(MIPI_PORT_CONTROL(pipe)) & ~BIT(31)); REG_READ(MIPI_PORT_CONTROL(pipe)); } dev_priv->dpi_panel_on[pipe] = false; } gma_power_end(dev); }
int mdfld_set_brightness(struct backlight_device *bd) { struct drm_device *dev = (struct drm_device *)bl_get_data(mdfld_backlight_device); struct drm_psb_private *dev_priv = dev->dev_private; int level = bd->props.brightness; DRM_DEBUG_DRIVER("backlight level set to %d\n", level); /* Perform value bounds checking */ if (level < BRIGHTNESS_MIN_LEVEL) level = BRIGHTNESS_MIN_LEVEL; if (gma_power_begin(dev, false)) { u32 adjusted_level = 0; /* * Adjust the backlight level with the percent in * dev_priv->blc_adj2 */ adjusted_level = level * dev_priv->blc_adj2; adjusted_level = adjusted_level / BLC_ADJUSTMENT_MAX; dev_priv->brightness_adjusted = adjusted_level; if (mdfld_get_panel_type(dev, 0) == TC35876X) { if (dev_priv->dpi_panel_on[0] || dev_priv->dpi_panel_on[2]) tc35876x_brightness_control(dev, dev_priv->brightness_adjusted); } else { if (dev_priv->dpi_panel_on[0]) mdfld_dsi_brightness_control(dev, 0, dev_priv->brightness_adjusted); } if (dev_priv->dpi_panel_on[2]) mdfld_dsi_brightness_control(dev, 2, dev_priv->brightness_adjusted); gma_power_end(dev); } /* cache the brightness for later use */ dev_priv->brightness = level; return 0; }
/* * Init DSI DPI encoder. * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector * return pointer of newly allocated DPI encoder, NULL on error */ struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev, struct mdfld_dsi_connector *dsi_connector, const struct panel_funcs *p_funcs) { struct mdfld_dsi_dpi_output *dpi_output = NULL; struct mdfld_dsi_config *dsi_config; struct drm_connector *connector = NULL; struct drm_encoder *encoder = NULL; int pipe; u32 data; int ret; pipe = dsi_connector->pipe; if (mdfld_get_panel_type(dev, pipe) != TC35876X) { dsi_config = mdfld_dsi_get_config(dsi_connector); /* panel hard-reset */ if (p_funcs->reset) { ret = p_funcs->reset(pipe); if (ret) { DRM_ERROR("Panel %d hard-reset failed\n", pipe); return NULL; } } /* panel drvIC init */ if (p_funcs->drv_ic_init) p_funcs->drv_ic_init(dsi_config, pipe); /* panel power mode detect */ ret = mdfld_dsi_get_power_mode(dsi_config, &data, false); if (ret) { DRM_ERROR("Panel %d get power mode failed\n", pipe); dsi_connector->status = connector_status_disconnected; } else { DRM_INFO("pipe %d power mode 0x%x\n", pipe, data); dsi_connector->status = connector_status_connected; } } dpi_output = kzalloc(sizeof(struct mdfld_dsi_dpi_output), GFP_KERNEL); if (!dpi_output) { DRM_ERROR("No memory\n"); return NULL; } if (dsi_connector->pipe) dpi_output->panel_on = 0; else dpi_output->panel_on = 0; dpi_output->dev = dev; if (mdfld_get_panel_type(dev, pipe) != TC35876X) dpi_output->p_funcs = p_funcs; dpi_output->first_boot = 1; /*get fixed mode*/ dsi_config = mdfld_dsi_get_config(dsi_connector); /*create drm encoder object*/ connector = &dsi_connector->base.base; encoder = &dpi_output->base.base.base; drm_encoder_init(dev, encoder, p_funcs->encoder_funcs, DRM_MODE_ENCODER_LVDS); drm_encoder_helper_add(encoder, p_funcs->encoder_helper_funcs); /*attach to given connector*/ drm_mode_connector_attach_encoder(connector, encoder); /*set possible crtcs and clones*/ if (dsi_connector->pipe) { encoder->possible_crtcs = (1 << 2); encoder->possible_clones = (1 << 1); } else { encoder->possible_crtcs = (1 << 0); encoder->possible_clones = (1 << 0); } dsi_connector->base.encoder = &dpi_output->base.base; return &dpi_output->base; }
void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct mdfld_dsi_encoder *dsi_encoder = mdfld_dsi_encoder(encoder); struct mdfld_dsi_dpi_output *dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder); struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder); struct drm_device *dev = dsi_config->dev; struct drm_psb_private *dev_priv = dev->dev_private; int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder); u32 pipeconf_reg = PIPEACONF; u32 dspcntr_reg = DSPACNTR; u32 pipeconf; u32 dspcntr; u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX; if (pipe == -1) return; pipeconf = dev_priv->pipeconf[pipe]; dspcntr = dev_priv->dspcntr[pipe]; if (pipe) { pipeconf_reg = PIPECCONF; dspcntr_reg = DSPCCNTR; } else { if (mdfld_get_panel_type(dev, pipe) == TC35876X) mipi &= (~0x03); /* Use all four lanes */ else mipi |= 2; } /*start up display island if it was shutdown*/ if (!gma_power_begin(dev, true)) return; if (mdfld_get_panel_type(dev, pipe) == TC35876X) { /* * The following logic is required to reset the bridge and * configure. This also starts the DSI clock at 200MHz. */ tc35876x_set_bridge_reset_state(dev, 0); /*Pull High Reset */ tc35876x_toshiba_bridge_panel_on(dev); udelay(100); /* Now start the DSI clock */ REG_WRITE(MRST_DPLL_A, 0x00); REG_WRITE(MRST_FPA0, 0xC1); REG_WRITE(MRST_DPLL_A, 0x00800000); udelay(500); REG_WRITE(MRST_DPLL_A, 0x80800000); if (REG_BIT_WAIT(pipeconf_reg, 1, 29)) dev_err(&dev->pdev->dev, "%s: DSI PLL lock timeout\n", __func__); REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x2A0c6008); mipi_set_properties(dsi_config, pipe); mdfld_mipi_config(dsi_config, pipe); mdfld_set_pipe_timing(dsi_config, pipe); REG_WRITE(DSPABASE, 0x00); REG_WRITE(DSPASIZE, ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); REG_WRITE(DSPACNTR, 0x98000000); REG_WRITE(DSPASURF, 0x00); REG_WRITE(VGACNTRL, 0x80000000); REG_WRITE(DEVICE_READY_REG, 0x00000001); REG_WRITE(MIPI_PORT_CONTROL(pipe), 0x80810000); } else { /*set up mipi port FIXME: do at init time */ REG_WRITE(MIPI_PORT_CONTROL(pipe), mipi); } REG_READ(MIPI_PORT_CONTROL(pipe)); if (mdfld_get_panel_type(dev, pipe) == TMD_VID) { /* NOP */ } else if (mdfld_get_panel_type(dev, pipe) == TC35876X) { /* set up DSI controller DPI interface */ mdfld_dsi_dpi_controller_init(dsi_config, pipe); /* Configure MIPI Bridge and Panel */ tc35876x_configure_lvds_bridge(dev); dev_priv->dpi_panel_on[pipe] = true; } else { /*turn on DPI interface*/ mdfld_dsi_dpi_turn_on(dpi_output, pipe); } /*set up pipe*/ REG_WRITE(pipeconf_reg, pipeconf); REG_READ(pipeconf_reg); /*set up display plane*/ REG_WRITE(dspcntr_reg, dspcntr); REG_READ(dspcntr_reg); msleep(20); /* FIXME: this should wait for vblank */ if (mdfld_get_panel_type(dev, pipe) == TMD_VID) { /* NOP */ } else if (mdfld_get_panel_type(dev, pipe) == TC35876X) { mdfld_dsi_dpi_turn_on(dpi_output, pipe); } else { /* init driver ic */ mdfld_dsi_tpo_ic_init(dsi_config, pipe); /*init backlight*/ mdfld_dsi_brightness_init(dsi_config, pipe); } gma_power_end(dev); }
void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *dsi_config, int pipe) { struct drm_device *dev = dsi_config->dev; int lane_count = dsi_config->lane_count; struct mdfld_dsi_dpi_timing dpi_timing; struct drm_display_mode *mode = dsi_config->mode; u32 val; /*un-ready device*/ REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), 0, 0, 0); /*init dsi adapter before kicking off*/ REG_WRITE(MIPI_CTRL_REG(pipe), 0x00000018); /*enable all interrupts*/ REG_WRITE(MIPI_INTR_EN_REG(pipe), 0xffffffff); /*set up func_prg*/ val = lane_count; val |= dsi_config->channel_num << DSI_DPI_VIRT_CHANNEL_OFFSET; switch (dsi_config->bpp) { case 16: val |= DSI_DPI_COLOR_FORMAT_RGB565; break; case 18: val |= DSI_DPI_COLOR_FORMAT_RGB666; break; case 24: val |= DSI_DPI_COLOR_FORMAT_RGB888; break; default: DRM_ERROR("unsupported color format, bpp = %d\n", dsi_config->bpp); } REG_WRITE(MIPI_DSI_FUNC_PRG_REG(pipe), val); REG_WRITE(MIPI_HS_TX_TIMEOUT_REG(pipe), (mode->vtotal * mode->htotal * dsi_config->bpp / (8 * lane_count)) & DSI_HS_TX_TIMEOUT_MASK); REG_WRITE(MIPI_LP_RX_TIMEOUT_REG(pipe), 0xffff & DSI_LP_RX_TIMEOUT_MASK); /*max value: 20 clock cycles of txclkesc*/ REG_WRITE(MIPI_TURN_AROUND_TIMEOUT_REG(pipe), 0x14 & DSI_TURN_AROUND_TIMEOUT_MASK); /*min 21 txclkesc, max: ffffh*/ REG_WRITE(MIPI_DEVICE_RESET_TIMER_REG(pipe), 0xffff & DSI_RESET_TIMER_MASK); REG_WRITE(MIPI_DPI_RESOLUTION_REG(pipe), mode->vdisplay << 16 | mode->hdisplay); /*set DPI timing registers*/ mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing, dsi_config->lane_count, dsi_config->bpp); REG_WRITE(MIPI_HSYNC_COUNT_REG(pipe), dpi_timing.hsync_count & DSI_DPI_TIMING_MASK); REG_WRITE(MIPI_HBP_COUNT_REG(pipe), dpi_timing.hbp_count & DSI_DPI_TIMING_MASK); REG_WRITE(MIPI_HFP_COUNT_REG(pipe), dpi_timing.hfp_count & DSI_DPI_TIMING_MASK); REG_WRITE(MIPI_HACTIVE_COUNT_REG(pipe), dpi_timing.hactive_count & DSI_DPI_TIMING_MASK); REG_WRITE(MIPI_VSYNC_COUNT_REG(pipe), dpi_timing.vsync_count & DSI_DPI_TIMING_MASK); REG_WRITE(MIPI_VBP_COUNT_REG(pipe), dpi_timing.vbp_count & DSI_DPI_TIMING_MASK); REG_WRITE(MIPI_VFP_COUNT_REG(pipe), dpi_timing.vfp_count & DSI_DPI_TIMING_MASK); REG_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT_REG(pipe), 0x46); /*min: 7d0 max: 4e20*/ REG_WRITE(MIPI_INIT_COUNT_REG(pipe), 0x000007d0); /*set up video mode*/ val = dsi_config->video_mode | DSI_DPI_COMPLETE_LAST_LINE; REG_WRITE(MIPI_VIDEO_MODE_FORMAT_REG(pipe), val); REG_WRITE(MIPI_EOT_DISABLE_REG(pipe), 0x00000000); REG_WRITE(MIPI_LP_BYTECLK_REG(pipe), 0x00000004); /*TODO: figure out how to setup these registers*/ if (mdfld_get_panel_type(dev, pipe) == TC35876X) REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x2A0c6008); else REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x150c3408); REG_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT_REG(pipe), (0xa << 16) | 0x14); if (mdfld_get_panel_type(dev, pipe) == TC35876X) tc35876x_set_bridge_reset_state(dev, 0); /*Pull High Reset */ /*set device ready*/ REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), 1, 0, 0); }
void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); struct mdfld_dsi_dpi_output *dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder); struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder); struct drm_device *dev = dsi_config->dev; struct drm_psb_private *dev_priv = dev->dev_private; int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder); u32 pipeconf_reg = PIPEACONF; u32 dspcntr_reg = DSPACNTR; u32 mipi_reg = MIPI; u32 reg_offset = 0; u32 pipeconf = dev_priv->pipeconf; u32 dspcntr = dev_priv->dspcntr; u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX; dev_dbg(dev->dev, "set mode %dx%d on pipe %d\n", mode->hdisplay, mode->vdisplay, pipe); if(pipe) { pipeconf_reg = PIPECCONF; dspcntr_reg = DSPCCNTR; mipi_reg = MIPI_C; reg_offset = MIPIC_REG_OFFSET; } else { mipi |= 2; } if (!gma_power_begin(dev, true)) return; /* Set up mipi port FIXME: do at init time */ REG_WRITE(mipi_reg, mipi); REG_READ(mipi_reg); /* Set up DSI controller DPI interface */ mdfld_dsi_dpi_controller_init(dsi_config, pipe); if (mdfld_get_panel_type(dev, pipe) != TMD_VID) { /* Turn on DPI interface */ mdfld_dsi_dpi_turn_on(dpi_output, pipe); } /* Set up pipe */ REG_WRITE(pipeconf_reg, pipeconf); REG_READ(pipeconf_reg); /* Set up display plane */ REG_WRITE(dspcntr_reg, dspcntr); REG_READ(dspcntr_reg); msleep(20); /* FIXME: this should wait for vblank */ dev_dbg(dev->dev, "State %x, power %d\n", REG_READ(MIPIA_INTR_STAT_REG + reg_offset), dpi_output->panel_on); if (mdfld_get_panel_type(dev, pipe) != TMD_VID) { /* Init driver ic */ mdfld_dsi_tpo_ic_init(dsi_config, pipe); /* Init backlight */ mdfld_dsi_brightness_init(dsi_config, pipe); } gma_power_end(dev); }
int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector, int pipe) { struct mdfld_dsi_pkg_sender *pkg_sender; struct mdfld_dsi_config *dsi_config = mdfld_dsi_get_config(dsi_connector); struct drm_device *dev = dsi_config->dev; struct drm_psb_private *dev_priv = dev->dev_private; const struct psb_offset *map = &dev_priv->regmap[pipe]; u32 mipi_val = 0; if (!dsi_connector) { DRM_ERROR("Invalid parameter\n"); return -EINVAL; } pkg_sender = dsi_connector->pkg_sender; if (!pkg_sender || IS_ERR(pkg_sender)) { pkg_sender = kzalloc(sizeof(struct mdfld_dsi_pkg_sender), GFP_KERNEL); if (!pkg_sender) { DRM_ERROR("Create DSI pkg sender failed\n"); return -ENOMEM; } dsi_connector->pkg_sender = (void *)pkg_sender; } pkg_sender->dev = dev; pkg_sender->dsi_connector = dsi_connector; pkg_sender->pipe = pipe; pkg_sender->pkg_num = 0; pkg_sender->panel_mode = 0; pkg_sender->status = MDFLD_DSI_PKG_SENDER_FREE; /*init regs*/ /* FIXME: should just copy the regmap ptr ? */ pkg_sender->dpll_reg = map->dpll; pkg_sender->dspcntr_reg = map->cntr; pkg_sender->pipeconf_reg = map->conf; pkg_sender->dsplinoff_reg = map->linoff; pkg_sender->dspsurf_reg = map->surf; pkg_sender->pipestat_reg = map->status; pkg_sender->mipi_intr_stat_reg = MIPI_INTR_STAT_REG(pipe); pkg_sender->mipi_lp_gen_data_reg = MIPI_LP_GEN_DATA_REG(pipe); pkg_sender->mipi_hs_gen_data_reg = MIPI_HS_GEN_DATA_REG(pipe); pkg_sender->mipi_lp_gen_ctrl_reg = MIPI_LP_GEN_CTRL_REG(pipe); pkg_sender->mipi_hs_gen_ctrl_reg = MIPI_HS_GEN_CTRL_REG(pipe); pkg_sender->mipi_gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe); pkg_sender->mipi_data_addr_reg = MIPI_DATA_ADD_REG(pipe); pkg_sender->mipi_data_len_reg = MIPI_DATA_LEN_REG(pipe); pkg_sender->mipi_cmd_addr_reg = MIPI_CMD_ADD_REG(pipe); pkg_sender->mipi_cmd_len_reg = MIPI_CMD_LEN_REG(pipe); /*init lock*/ spin_lock_init(&pkg_sender->lock); if (mdfld_get_panel_type(dev, pipe) != TC35876X) { /** * For video mode, don't enable DPI timing output here, * will init the DPI timing output during mode setting. */ mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX; if (pipe == 0) mipi_val |= 0x2; REG_WRITE(MIPI_PORT_CONTROL(pipe), mipi_val); REG_READ(MIPI_PORT_CONTROL(pipe)); /* do dsi controller init */ mdfld_dsi_controller_init(dsi_config, pipe); } return 0; }