/* * Init DSI DBI encoder. * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector * return pointer of newly allocated DBI encoder, NULL on error */ struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev, struct mdfld_dsi_connector *dsi_connector, struct panel_funcs *p_funcs) { struct drm_psb_private *dev_priv = (struct drm_psb_private *)dev->dev_private; struct mdfld_dsi_dbi_output *dbi_output = NULL; struct mdfld_dsi_config *dsi_config; struct drm_connector *connector = NULL; struct drm_encoder *encoder = NULL; struct drm_display_mode *fixed_mode = NULL; struct psb_gtt *pg = dev_priv ? (dev_priv->pg) : NULL; #ifdef CONFIG_MDFLD_DSI_DPU struct mdfld_dbi_dpu_info *dpu_info = dev_priv ? (dev_priv->dbi_dpu_info) : NULL; #else struct mdfld_dbi_dsr_info *dsr_info = dev_priv ? (dev_priv->dbi_dsr_info) : NULL; #endif int pipe; int ret; PSB_DEBUG_ENTRY("\n"); if (!pg || !dsi_connector || !p_funcs) { DRM_ERROR("Invalid parameters\n"); return NULL; } dsi_config = mdfld_dsi_get_config(dsi_connector); pipe = dsi_connector->pipe; if (p_funcs && p_funcs->reset) p_funcs->reset(dsi_config); /*detect panel connection stauts*/ if (p_funcs->detect) { ret = p_funcs->detect(dsi_config); if (ret) { DRM_INFO("Fail to detect Panel on pipe %d\n", pipe); dsi_connector->status = connector_status_disconnected; } else { DRM_INFO("Panel on pipe %d is connected\n", pipe); dsi_connector->status = connector_status_connected; } } else { /*use the default config*/ if (pipe == 0) dsi_connector->status = connector_status_connected; else dsi_connector->status = connector_status_disconnected; } /*init DSI controller*/ if (p_funcs->dsi_controller_init) p_funcs->dsi_controller_init(dsi_config); if (dsi_connector->status == connector_status_connected) { if (pipe == 0) dev_priv->panel_desc |= DISPLAY_A; if (pipe == 2) dev_priv->panel_desc |= DISPLAY_C; } /* TODO: get panel info from DDB */ dbi_output = kzalloc(sizeof(struct mdfld_dsi_dbi_output), GFP_KERNEL); if (!dbi_output) { DRM_ERROR("No memory\n"); return NULL; } if (dsi_connector->pipe == 0) { dbi_output->channel_num = 0; dev_priv->dbi_output = dbi_output; } else if (dsi_connector->pipe == 2) { dbi_output->channel_num = 1; dev_priv->dbi_output2 = dbi_output; } else { DRM_ERROR("only support 2 DSI outputs\n"); goto out_err1; } dbi_output->dev = dev; dbi_output->p_funcs = p_funcs; /*get fixed mode*/ fixed_mode = dsi_config->fixed_mode; dbi_output->panel_fixed_mode = fixed_mode; /*create drm encoder object*/ connector = &dsi_connector->base.base; encoder = &dbi_output->base.base; drm_encoder_init(dev, encoder, &dsi_dbi_generic_encoder_funcs, DRM_MODE_ENCODER_DSI); drm_encoder_helper_add(encoder, &dsi_dbi_generic_encoder_helper_funcs); /*attach to given connector*/ drm_mode_connector_attach_encoder(connector, encoder); connector->encoder = 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); } dev_priv->dsr_fb_update = 0; dev_priv->b_dsr_enable = false; dev_priv->exit_idle = mdfld_dsi_dbi_exit_dsr; dev_priv->b_async_flip_enable = false; #if defined(CONFIG_MDFLD_DSI_DPU) || defined(CONFIG_MDFLD_DSI_DSR) dev_priv->b_dsr_enable_config = true; #endif /*CONFIG_MDFLD_DSI_DSR*/ dbi_output->first_boot = true; dbi_output->mode_flags = MODE_SETTING_IN_ENCODER; #ifdef CONFIG_MDFLD_DSI_DPU /*add this output to dpu_info*/ if (dsi_connector->status == connector_status_connected) { if (dsi_connector->pipe == 0) dpu_info->dbi_outputs[0] = dbi_output; else dpu_info->dbi_outputs[1] = dbi_output; dpu_info->dbi_output_num++; } #else /*CONFIG_MDFLD_DSI_DPU*/ if (dsi_connector->status == connector_status_connected) { /*add this output to dsr_info*/ if (dsi_connector->pipe == 0) dsr_info->dbi_outputs[0] = dbi_output; else dsr_info->dbi_outputs[1] = dbi_output; dsr_info->dbi_output_num++; } #endif PSB_DEBUG_ENTRY("successfully\n"); return &dbi_output->base; out_err1: kfree(dbi_output); return NULL; }
/* * 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; }
/* * 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, struct panel_funcs *p_funcs) { struct drm_psb_private *dev_priv = dev->dev_private; struct mdfld_dsi_dpi_output *dpi_output = NULL; struct mdfld_dsi_config *dsi_config; struct drm_connector *connector = NULL; struct drm_encoder *encoder = NULL; struct drm_display_mode *fixed_mode = NULL; int pipe; int ret; PSB_DEBUG_ENTRY("[DISPLAY] %s\n", __func__); if (!dsi_connector || !p_funcs) { DRM_ERROR("Invalid parameters\n"); return NULL; } dsi_config = mdfld_dsi_get_config(dsi_connector); pipe = dsi_connector->pipe; /*detect panel connection stauts*/ if (p_funcs->detect) { ret = p_funcs->detect(dsi_config); if (ret) { DRM_INFO("Detecting Panel %d, Not connected\n", pipe); dsi_connector->status = connector_status_disconnected; } else { PSB_DEBUG_ENTRY("Panel %d is connected\n", pipe); dsi_connector->status = connector_status_connected; } if (dsi_connector->status == connector_status_disconnected && pipe == 0) { DRM_ERROR("Primary panel disconnected\n"); return NULL; } } else { /*use the default config*/ if (pipe == 0) dsi_connector->status = connector_status_connected; else dsi_connector->status = connector_status_disconnected; } /*init DSI controller*/ if (p_funcs->dsi_controller_init) p_funcs->dsi_controller_init(dsi_config); /** * TODO: can we keep these code out of display driver as * it will make display driver hard to be maintained */ if (dsi_connector->status == connector_status_connected) { if (pipe == 0) dev_priv->panel_desc |= DISPLAY_A; if (pipe == 2) dev_priv->panel_desc |= DISPLAY_C; } dpi_output = kzalloc(sizeof(struct mdfld_dsi_dpi_output), GFP_KERNEL); if (!dpi_output) { DRM_ERROR("No memory\n"); return NULL; } dpi_output->dev = dev; dpi_output->p_funcs = p_funcs; dpi_output->first_boot = 1; /*get fixed mode*/ fixed_mode = dsi_config->fixed_mode; /*create drm encoder object*/ connector = &dsi_connector->base.base; encoder = &dpi_output->base.base; drm_encoder_init(dev, encoder, &dsi_dpi_generic_encoder_funcs, DRM_MODE_ENCODER_DSI); drm_encoder_helper_add(encoder, &dsi_dpi_generic_encoder_helper_funcs); /*attach to given connector*/ drm_mode_connector_attach_encoder(connector, encoder); connector->encoder = 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); } dev_priv->dsr_fb_update = 0; dev_priv->b_dsr_enable = false; dev_priv->exit_idle = NULL; #if defined(CONFIG_MDFLD_DSI_DPU) || defined(CONFIG_MDFLD_DSI_DSR) dev_priv->b_dsr_enable_config = true; #endif /*CONFIG_MDFLD_DSI_DSR*/ PSB_DEBUG_ENTRY("successfully\n"); return &dpi_output->base; }
/* * Init DSI DBI encoder. * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector * return pointer of newly allocated DBI encoder, NULL on error */ struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev, struct mdfld_dsi_connector *dsi_connector, struct panel_funcs *p_funcs) { struct drm_psb_private *dev_priv = dev->dev_private; struct mdfld_dsi_dbi_output *dbi_output = NULL; struct mdfld_dsi_config *dsi_config; struct drm_connector *connector = NULL; struct drm_encoder *encoder = NULL; struct drm_display_mode *fixed_mode = NULL; struct psb_gtt *pg = dev_priv ? (&dev_priv->gtt) : NULL; struct mdfld_dbi_dpu_info *dpu_info = dev_priv ? (dev_priv->dbi_dpu_info) : NULL; struct mdfld_dbi_dsr_info *dsr_info = dev_priv ? (dev_priv->dbi_dsr_info) : NULL; u32 data = 0; int pipe; int ret; if (!pg || !dsi_connector || !p_funcs) { WARN_ON(1); return NULL; } dsi_config = mdfld_dsi_get_config(dsi_connector); pipe = dsi_connector->pipe; /*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, MDFLD_DSI_HS_TRANSMISSION); 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; } /*TODO: get panel info from DDB*/ dbi_output = kzalloc(sizeof(struct mdfld_dsi_dbi_output), GFP_KERNEL); if (!dbi_output) { dev_err(dev->dev, "No memory\n"); return NULL; } if (dsi_connector->pipe == 0) { dbi_output->channel_num = 0; dev_priv->dbi_output = dbi_output; } else if (dsi_connector->pipe == 2) { dbi_output->channel_num = 1; dev_priv->dbi_output2 = dbi_output; } else { dev_err(dev->dev, "only support 2 DSI outputs\n"); goto out_err1; } dbi_output->dev = dev; dbi_output->p_funcs = p_funcs; fixed_mode = dsi_config->fixed_mode; dbi_output->panel_fixed_mode = fixed_mode; /* Create drm encoder object */ connector = &dsi_connector->base.base; encoder = &dbi_output->base.base; drm_encoder_init(dev, encoder, p_funcs->encoder_funcs, DRM_MODE_ENCODER_MIPI); 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); } dev_priv->dsr_fb_update = 0; dev_priv->dsr_enable = false; dev_priv->exit_idle = mdfld_dsi_dbi_exit_dsr; dbi_output->first_boot = true; dbi_output->mode_flags = MODE_SETTING_IN_ENCODER; /* Add this output to dpu_info if in DPU mode */ if (dpu_info && dsi_connector->status == connector_status_connected) { if (dsi_connector->pipe == 0) dpu_info->dbi_outputs[0] = dbi_output; else dpu_info->dbi_outputs[1] = dbi_output; dpu_info->dbi_output_num++; } else if (dsi_connector->status == connector_status_connected) { /* Add this output to dsr_info if not */ if (dsi_connector->pipe == 0) dsr_info->dbi_outputs[0] = dbi_output; else dsr_info->dbi_outputs[1] = dbi_output; dsr_info->dbi_output_num++; } return &dbi_output->base; out_err1: kfree(dbi_output); return NULL; }
/* * 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, 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; struct drm_display_mode *fixed_mode = NULL; int pipe; u32 data; int ret; if (!dsi_connector || !p_funcs) { WARN_ON(1); return NULL; } dsi_config = mdfld_dsi_get_config(dsi_connector); pipe = dsi_connector->pipe; /* 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, MDFLD_DSI_LP_TRANSMISSION); 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) { dev_err(dev->dev, "No memory for dsi_dpi_output\n"); return NULL; } if(dsi_connector->pipe) dpi_output->panel_on = 0; else dpi_output->panel_on = 0; dpi_output->dev = dev; dpi_output->p_funcs = p_funcs; dpi_output->first_boot = 1; /* Get fixed mode */ dsi_config = mdfld_dsi_get_config(dsi_connector); fixed_mode = dsi_config->fixed_mode; /* Create drm encoder object */ connector = &dsi_connector->base.base; encoder = &dpi_output->base.base; /* * On existing hardware this will be a panel of some form, * if future devices also have HDMI bridges this will need * revisiting */ 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); } return &dpi_output->base; }
/* * 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) { struct drm_psb_private *dev_priv = dev->dev_private; 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; PSB_DEBUG_ENTRY("\n"); if (!dsi_connector) { DRM_ERROR("Invalid parameters\n"); return NULL; } dsi_config = mdfld_dsi_get_config(dsi_connector); pipe = dsi_connector->pipe; 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; } dpi_output->dev = dev; dpi_output->first_boot = 1; if (pipe) dev_priv->dpi_output2 = dpi_output; else dev_priv->dpi_output = dpi_output; /*create drm encoder object*/ connector = &dsi_connector->base.base; encoder = &dpi_output->base.base; drm_encoder_init(dev, encoder, &dsi_dpi_generic_encoder_funcs, DRM_MODE_ENCODER_DSI); drm_encoder_helper_add(encoder, &dsi_dpi_generic_encoder_helper_funcs); /*attach to given connector*/ drm_mode_connector_attach_encoder(connector, encoder); connector->encoder = 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); } dev_priv->dsr_fb_update = 0; dev_priv->b_dsr_enable = false; dev_priv->exit_idle = mdfld_dsi_dpi_exit_idle; #if defined(CONFIG_MDFLD_DSI_DPU) || defined(CONFIG_MDFLD_DSI_DSR) dev_priv->b_dsr_enable_config = true; #endif /*CONFIG_MDFLD_DSI_DSR*/ encoder_shutdown = encoder; PSB_DEBUG_ENTRY("successfully\n"); return &dpi_output->base; }
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; }