static int dw_mipi_dsi_gen_pkt_hdr_write(struct dw_mipi_dsi *dsi, u32 hdr_val) { int ret; u32 val, mask; ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS, val, !(val & GEN_CMD_FULL), 1000, CMD_PKT_STATUS_TIMEOUT_US); if (ret < 0) { DRM_DEV_ERROR(dsi->dev, "failed to get available command FIFO\n"); return ret; } dsi_write(dsi, DSI_GEN_HDR, hdr_val); mask = GEN_CMD_EMPTY | GEN_PLD_W_EMPTY; ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS, val, (val & mask) == mask, 1000, CMD_PKT_STATUS_TIMEOUT_US); if (ret < 0) { DRM_DEV_ERROR(dsi->dev, "failed to write command FIFO\n"); return ret; } return 0; }
static int a6xx_rpmh_start(struct a6xx_gmu *gmu) { int ret; u32 val; gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 1 << 1); /* Wait for the register to finish posting */ wmb(); ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_RSCC_CONTROL_ACK, val, val & (1 << 1), 100, 10000); if (ret) { DRM_DEV_ERROR(gmu->dev, "Unable to power on the GPU RSC\n"); return ret; } ret = gmu_poll_timeout(gmu, REG_A6XX_RSCC_SEQ_BUSY_DRV0, val, !val, 100, 10000); if (ret) { DRM_DEV_ERROR(gmu->dev, "GPU RSC sequence stuck while waking up the GPU\n"); return ret; } gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 0); /* Set up CX GMU counter 0 to count busy ticks */ gmu_write(gmu, REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_MASK, 0xff000000); gmu_rmw(gmu, REG_A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0, 0xff, 0x20); /* Enable the power counter */ gmu_write(gmu, REG_A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 1); return 0; }
static int rockchip_hdmi_parse_dt(struct rockchip_hdmi *hdmi) { struct device_node *np = hdmi->dev->of_node; hdmi->regmap = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); if (IS_ERR(hdmi->regmap)) { DRM_DEV_ERROR(hdmi->dev, "Unable to get rockchip,grf\n"); return PTR_ERR(hdmi->regmap); } hdmi->vpll_clk = devm_clk_get(hdmi->dev, "vpll"); if (PTR_ERR(hdmi->vpll_clk) == -ENOENT) { hdmi->vpll_clk = NULL; } else if (PTR_ERR(hdmi->vpll_clk) == -EPROBE_DEFER) { return -EPROBE_DEFER; } else if (IS_ERR(hdmi->vpll_clk)) { DRM_DEV_ERROR(hdmi->dev, "failed to get grf clock\n"); return PTR_ERR(hdmi->vpll_clk); } hdmi->grf_clk = devm_clk_get(hdmi->dev, "grf"); if (PTR_ERR(hdmi->grf_clk) == -ENOENT) { hdmi->grf_clk = NULL; } else if (PTR_ERR(hdmi->grf_clk) == -EPROBE_DEFER) { return -EPROBE_DEFER; } else if (IS_ERR(hdmi->grf_clk)) { DRM_DEV_ERROR(hdmi->dev, "failed to get grf clock\n"); return PTR_ERR(hdmi->grf_clk); } return 0; }
static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder) { struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder); u32 val; int ret; if (hdmi->chip_data->lcdsel_grf_reg < 0) return; ret = drm_of_encoder_active_endpoint_id(hdmi->dev->of_node, encoder); if (ret) val = hdmi->chip_data->lcdsel_lit; else val = hdmi->chip_data->lcdsel_big; ret = clk_prepare_enable(hdmi->grf_clk); if (ret < 0) { DRM_DEV_ERROR(hdmi->dev, "failed to enable grfclk %d\n", ret); return; } ret = regmap_write(hdmi->regmap, hdmi->chip_data->lcdsel_grf_reg, val); if (ret != 0) DRM_DEV_ERROR(hdmi->dev, "Could not write to GRF: %d\n", ret); clk_disable_unprepare(hdmi->grf_clk); DRM_DEV_DEBUG(hdmi->dev, "vop %s output to hdmi\n", ret ? "LIT" : "BIG"); }
static int pingpong_tearcheck_enable(struct drm_encoder *encoder) { struct mdp5_kms *mdp5_kms = get_kms(encoder); struct mdp5_hw_mixer *mixer = mdp5_crtc_get_mixer(encoder->crtc); int pp_id = mixer->pp; int ret; ret = clk_set_rate(mdp5_kms->vsync_clk, clk_round_rate(mdp5_kms->vsync_clk, VSYNC_CLK_RATE)); if (ret) { DRM_DEV_ERROR(encoder->dev->dev, "vsync_clk clk_set_rate failed, %d\n", ret); return ret; } ret = clk_prepare_enable(mdp5_kms->vsync_clk); if (ret) { DRM_DEV_ERROR(encoder->dev->dev, "vsync_clk clk_prepare_enable failed, %d\n", ret); return ret; } mdp5_write(mdp5_kms, REG_MDP5_PP_TEAR_CHECK_EN(pp_id), 1); return 0; }
/* * mdp5_ctl_pair() - Associate 2 booked CTLs for single FLUSH */ int mdp5_ctl_pair(struct mdp5_ctl *ctlx, struct mdp5_ctl *ctly, bool enable) { struct mdp5_ctl_manager *ctl_mgr = ctlx->ctlm; struct mdp5_kms *mdp5_kms = get_kms(ctl_mgr); /* do nothing silently if hw doesn't support */ if (!ctl_mgr->single_flush_supported) return 0; if (!enable) { ctlx->pair = NULL; ctly->pair = NULL; mdp5_write(mdp5_kms, REG_MDP5_SPARE_0, 0); return 0; } else if ((ctlx->pair != NULL) || (ctly->pair != NULL)) { DRM_DEV_ERROR(ctl_mgr->dev->dev, "CTLs already paired\n"); return -EINVAL; } else if (!(ctlx->status & ctly->status & CTL_STAT_BOOKED)) { DRM_DEV_ERROR(ctl_mgr->dev->dev, "Only pair booked CTLs\n"); return -EINVAL; } ctlx->pair = ctly; ctly->pair = ctlx; mdp5_write(mdp5_kms, REG_MDP5_SPARE_0, MDP5_SPARE_0_SPLIT_DPL_SINGLE_FLUSH_EN); return 0; }
static int dw_mipi_dsi_get_lane_bps(struct dw_mipi_dsi *dsi, struct drm_display_mode *mode) { unsigned int i, pre; unsigned long mpclk, pllref, tmp; unsigned int m = 1, n = 1, target_mbps = 1000; unsigned int max_mbps = dptdin_map[ARRAY_SIZE(dptdin_map) - 1].max_mbps; int bpp; bpp = mipi_dsi_pixel_format_to_bpp(dsi->format); if (bpp < 0) { DRM_DEV_ERROR(dsi->dev, "failed to get bpp for pixel format %d\n", dsi->format); return bpp; } mpclk = DIV_ROUND_UP(mode->clock, MSEC_PER_SEC); if (mpclk) { /* take 1 / 0.8, since mbps must big than bandwidth of RGB */ tmp = mpclk * (bpp / dsi->lanes) * 10 / 8; if (tmp < max_mbps) target_mbps = tmp; else DRM_DEV_ERROR(dsi->dev, "DPHY clock frequency is out of range\n"); } pllref = DIV_ROUND_UP(clk_get_rate(dsi->pllref_clk), USEC_PER_SEC); tmp = pllref; /* * The limits on the PLL divisor are: * * 5MHz <= (pllref / n) <= 40MHz * * we walk over these values in descreasing order so that if we hit * an exact match for target_mbps it is more likely that "m" will be * even. * * TODO: ensure that "m" is even after this loop. */ for (i = pllref / 5; i > (pllref / 40); i--) { pre = pllref / i; if ((tmp > (target_mbps % pre)) && (target_mbps / pre < 512)) { tmp = target_mbps % pre; n = i; m = target_mbps / pre; } if (tmp == 0) break; } dsi->lane_mbps = pllref / n * m; dsi->input_div = n; dsi->feedback_div = m; return 0; }
static void mdp4_lcdc_encoder_enable(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; struct mdp4_lcdc_encoder *mdp4_lcdc_encoder = to_mdp4_lcdc_encoder(encoder); unsigned long pc = mdp4_lcdc_encoder->pixclock; struct mdp4_kms *mdp4_kms = get_kms(encoder); struct drm_panel *panel; uint32_t config; int i, ret; if (WARN_ON(mdp4_lcdc_encoder->enabled)) return; /* TODO: hard-coded for 18bpp: */ config = MDP4_DMA_CONFIG_R_BPC(BPC6) | MDP4_DMA_CONFIG_G_BPC(BPC6) | MDP4_DMA_CONFIG_B_BPC(BPC6) | MDP4_DMA_CONFIG_PACK(0x21) | MDP4_DMA_CONFIG_DEFLKR_EN | MDP4_DMA_CONFIG_DITHER_EN; if (!of_property_read_bool(dev->dev->of_node, "qcom,lcdc-align-lsb")) config |= MDP4_DMA_CONFIG_PACK_ALIGN_MSB; mdp4_crtc_set_config(encoder->crtc, config); mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV, 0); bs_set(mdp4_lcdc_encoder, 1); for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) { ret = regulator_enable(mdp4_lcdc_encoder->regs[i]); if (ret) DRM_DEV_ERROR(dev->dev, "failed to enable regulator: %d\n", ret); } DBG("setting lcdc_clk=%lu", pc); ret = clk_set_rate(mdp4_lcdc_encoder->lcdc_clk, pc); if (ret) DRM_DEV_ERROR(dev->dev, "failed to configure lcdc_clk: %d\n", ret); ret = clk_prepare_enable(mdp4_lcdc_encoder->lcdc_clk); if (ret) DRM_DEV_ERROR(dev->dev, "failed to enable lcdc_clk: %d\n", ret); panel = of_drm_find_panel(mdp4_lcdc_encoder->panel_node); if (!IS_ERR(panel)) { drm_panel_prepare(panel); drm_panel_enable(panel); } setup_phy(encoder); mdp4_write(mdp4_kms, REG_MDP4_LCDC_ENABLE, 1); mdp4_lcdc_encoder->enabled = true; }
static ssize_t dw_mipi_dsi_host_transfer(struct mipi_dsi_host *host, const struct mipi_dsi_msg *msg) { struct dw_mipi_dsi *dsi = host_to_dsi(host); int ret; dw_mipi_message_config(dsi, msg); switch (msg->type) { case MIPI_DSI_DCS_SHORT_WRITE: case MIPI_DSI_DCS_SHORT_WRITE_PARAM: case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE: ret = dw_mipi_dsi_dcs_short_write(dsi, msg); break; case MIPI_DSI_DCS_LONG_WRITE: ret = dw_mipi_dsi_dcs_long_write(dsi, msg); break; default: DRM_DEV_ERROR(dsi->dev, "unsupported message type 0x%02x\n", msg->type); ret = -EINVAL; } return ret; }
int panfrost_devfreq_init(struct panfrost_device *pfdev) { int ret; struct dev_pm_opp *opp; if (!pfdev->regulator) return 0; ret = dev_pm_opp_of_add_table(&pfdev->pdev->dev); if (ret) return ret; panfrost_devfreq_reset(pfdev); pfdev->devfreq.cur_freq = clk_get_rate(pfdev->clock); opp = devfreq_recommended_opp(&pfdev->pdev->dev, &pfdev->devfreq.cur_freq, 0); if (IS_ERR(opp)) return PTR_ERR(opp); panfrost_devfreq_profile.initial_freq = pfdev->devfreq.cur_freq; dev_pm_opp_put(opp); pfdev->devfreq.devfreq = devm_devfreq_add_device(&pfdev->pdev->dev, &panfrost_devfreq_profile, "simple_ondemand", NULL); if (IS_ERR(pfdev->devfreq.devfreq)) { DRM_DEV_ERROR(&pfdev->pdev->dev, "Couldn't initialize GPU devfreq\n"); ret = PTR_ERR(pfdev->devfreq.devfreq); pfdev->devfreq.devfreq = NULL; return ret; } return 0; }
/* * drm_iommu_attach_device- attach device to iommu mapping * * @drm_dev: DRM device * @subdrv_dev: device to be attach * * This function should be called by sub drivers to attach it to iommu * mapping. */ static int drm_iommu_attach_device(struct drm_device *drm_dev, struct device *subdrv_dev) { struct exynos_drm_private *priv = drm_dev->dev_private; int ret; if (get_dma_ops(priv->dma_dev) != get_dma_ops(subdrv_dev)) { DRM_DEV_ERROR(subdrv_dev, "Device %s lacks support for IOMMU\n", dev_name(subdrv_dev)); return -EINVAL; } ret = configure_dma_max_seg_size(subdrv_dev); if (ret) return ret; if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)) { if (to_dma_iommu_mapping(subdrv_dev)) arm_iommu_detach_device(subdrv_dev); ret = arm_iommu_attach_device(subdrv_dev, priv->mapping); } else if (IS_ENABLED(CONFIG_IOMMU_DMA)) { ret = iommu_attach_device(priv->mapping, subdrv_dev); } if (ret) clear_dma_max_seg_size(subdrv_dev); return 0; }
/* Let the GMU know that we are about to go into slumber */ static int a6xx_gmu_notify_slumber(struct a6xx_gmu *gmu) { int ret; /* Disable the power counter so the GMU isn't busy */ gmu_write(gmu, REG_A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 0); /* Disable SPTP_PC if the CPU is responsible for it */ if (gmu->idle_level < GMU_IDLE_STATE_SPTP) a6xx_sptprac_disable(gmu); /* Tell the GMU to get ready to slumber */ gmu_write(gmu, REG_A6XX_GMU_BOOT_SLUMBER_OPTION, 1); ret = a6xx_gmu_set_oob(gmu, GMU_OOB_BOOT_SLUMBER); a6xx_gmu_clear_oob(gmu, GMU_OOB_BOOT_SLUMBER); if (!ret) { /* Check to see if the GMU really did slumber */ if (gmu_read(gmu, REG_A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE) != 0x0f) { DRM_DEV_ERROR(gmu->dev, "The GMU did not go into slumber\n"); ret = -ETIMEDOUT; } } /* Put fence into allow mode */ gmu_write(gmu, REG_A6XX_GMU_AO_AHB_FENCE_CTRL, 0); return ret; }
static struct drm_framebuffer * drm_gem_fb_alloc(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **obj, unsigned int num_planes, const struct drm_framebuffer_funcs *funcs) { struct drm_framebuffer *fb; int ret, i; fb = kzalloc(sizeof(*fb), GFP_KERNEL); if (!fb) return ERR_PTR(-ENOMEM); drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd); for (i = 0; i < num_planes; i++) fb->obj[i] = obj[i]; ret = drm_framebuffer_init(dev, fb, funcs); if (ret) { DRM_DEV_ERROR(dev->dev, "Failed to init framebuffer: %d\n", ret); kfree(fb); return ERR_PTR(ret); } return fb; }
static int a6xx_gmu_pwrlevels_probe(struct a6xx_gmu *gmu) { struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; struct msm_gpu *gpu = &adreno_gpu->base; int ret = 0; /* * The GMU handles its own frequency switching so build a list of * available frequencies to send during initialization */ ret = dev_pm_opp_of_add_table(gmu->dev); if (ret) { DRM_DEV_ERROR(gmu->dev, "Unable to set the OPP table for the GMU\n"); return ret; } gmu->nr_gmu_freqs = a6xx_gmu_build_freq_table(gmu->dev, gmu->gmu_freqs, ARRAY_SIZE(gmu->gmu_freqs)); /* * The GMU also handles GPU frequency switching so build a list * from the GPU OPP table */ gmu->nr_gpu_freqs = a6xx_gmu_build_freq_table(&gpu->pdev->dev, gmu->gpu_freqs, ARRAY_SIZE(gmu->gpu_freqs)); /* Build the list of RPMh votes that we'll send to the GMU */ return a6xx_gmu_rpmh_votes_init(gmu); }
static int interface_init(struct mdp5_kms *mdp5_kms) { struct drm_device *dev = mdp5_kms->dev; const struct mdp5_cfg_hw *hw_cfg; const enum mdp5_intf_type *intf_types; int i; hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg); intf_types = hw_cfg->intf.connect; for (i = 0; i < ARRAY_SIZE(hw_cfg->intf.connect); i++) { struct mdp5_interface *intf; if (intf_types[i] == INTF_DISABLED) continue; intf = kzalloc(sizeof(*intf), GFP_KERNEL); if (!intf) { DRM_DEV_ERROR(dev->dev, "failed to construct INTF%d\n", i); return -ENOMEM; } intf->num = i; intf->type = intf_types[i]; intf->mode = MDP5_INTF_MODE_NONE; intf->idx = mdp5_kms->num_intfs; mdp5_kms->intfs[mdp5_kms->num_intfs++] = intf; } return 0; }
static int hwmixer_init(struct mdp5_kms *mdp5_kms) { struct drm_device *dev = mdp5_kms->dev; const struct mdp5_cfg_hw *hw_cfg; int i, ret; hw_cfg = mdp5_cfg_get_hw_config(mdp5_kms->cfg); for (i = 0; i < hw_cfg->lm.count; i++) { struct mdp5_hw_mixer *mixer; mixer = mdp5_mixer_init(&hw_cfg->lm.instances[i]); if (IS_ERR(mixer)) { ret = PTR_ERR(mixer); DRM_DEV_ERROR(dev->dev, "failed to construct LM%d (%d)\n", i, ret); return ret; } mixer->idx = mdp5_kms->num_hwmixers; mdp5_kms->hwmixers[mdp5_kms->num_hwmixers++] = mixer; } return 0; }
static int pingpong_tearcheck_setup(struct drm_encoder *encoder, struct drm_display_mode *mode) { struct mdp5_kms *mdp5_kms = get_kms(encoder); struct device *dev = encoder->dev->dev; u32 total_lines_x100, vclks_line, cfg; long vsync_clk_speed; struct mdp5_hw_mixer *mixer = mdp5_crtc_get_mixer(encoder->crtc); int pp_id = mixer->pp; if (IS_ERR_OR_NULL(mdp5_kms->vsync_clk)) { DRM_DEV_ERROR(dev, "vsync_clk is not initialized\n"); return -EINVAL; } total_lines_x100 = mode->vtotal * drm_mode_vrefresh(mode); if (!total_lines_x100) { DRM_DEV_ERROR(dev, "%s: vtotal(%d) or vrefresh(%d) is 0\n", __func__, mode->vtotal, drm_mode_vrefresh(mode)); return -EINVAL; } vsync_clk_speed = clk_round_rate(mdp5_kms->vsync_clk, VSYNC_CLK_RATE); if (vsync_clk_speed <= 0) { DRM_DEV_ERROR(dev, "vsync_clk round rate failed %ld\n", vsync_clk_speed); return -EINVAL; } vclks_line = vsync_clk_speed * 100 / total_lines_x100; cfg = MDP5_PP_SYNC_CONFIG_VSYNC_COUNTER_EN | MDP5_PP_SYNC_CONFIG_VSYNC_IN_EN; cfg |= MDP5_PP_SYNC_CONFIG_VSYNC_COUNT(vclks_line); mdp5_write(mdp5_kms, REG_MDP5_PP_SYNC_CONFIG_VSYNC(pp_id), cfg); mdp5_write(mdp5_kms, REG_MDP5_PP_SYNC_CONFIG_HEIGHT(pp_id), 0xfff0); mdp5_write(mdp5_kms, REG_MDP5_PP_VSYNC_INIT_VAL(pp_id), mode->vdisplay); mdp5_write(mdp5_kms, REG_MDP5_PP_RD_PTR_IRQ(pp_id), mode->vdisplay + 1); mdp5_write(mdp5_kms, REG_MDP5_PP_START_POS(pp_id), mode->vdisplay); mdp5_write(mdp5_kms, REG_MDP5_PP_SYNC_THRESH(pp_id), MDP5_PP_SYNC_THRESH_START(4) | MDP5_PP_SYNC_THRESH_CONTINUE(4)); return 0; }
/* Gracefully try to shut down the GMU and by extension the GPU */ static void a6xx_gmu_shutdown(struct a6xx_gmu *gmu) { struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; struct msm_gpu *gpu = &adreno_gpu->base; u32 val; /* * The GMU may still be in slumber unless the GPU started so check and * skip putting it back into slumber if so */ val = gmu_read(gmu, REG_A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE); if (val != 0xf) { int ret = a6xx_gmu_wait_for_idle(gmu); /* If the GMU isn't responding assume it is hung */ if (ret) { a6xx_gmu_force_off(gmu); return; } /* Clear the VBIF pipe before shutting down */ gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0xf); spin_until((gpu_read(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL1) & 0xf) == 0xf); gpu_write(gpu, REG_A6XX_VBIF_XIN_HALT_CTRL0, 0); /* tell the GMU we want to slumber */ a6xx_gmu_notify_slumber(gmu); ret = gmu_poll_timeout(gmu, REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS, val, !(val & A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS_GPUBUSYIGNAHB), 100, 10000); /* * Let the user know we failed to slumber but don't worry too * much because we are powering down anyway */ if (ret) DRM_DEV_ERROR(gmu->dev, "Unable to slumber GMU: status = 0%x/0%x\n", gmu_read(gmu, REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS), gmu_read(gmu, REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS2)); } /* Turn off HFI */ a6xx_hfi_stop(gmu); /* Stop the interrupts and mask the hardware */ a6xx_gmu_irq_disable(gmu); /* Tell RPMh to power off the GPU */ a6xx_rpmh_stop(gmu); }
static int st7735r_probe(struct spi_device *spi) { struct device *dev = &spi->dev; struct mipi_dbi *mipi; struct gpio_desc *dc; u32 rotation = 0; int ret; mipi = devm_kzalloc(dev, sizeof(*mipi), GFP_KERNEL); if (!mipi) return -ENOMEM; mipi->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(mipi->reset)) { DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n"); return PTR_ERR(mipi->reset); } dc = devm_gpiod_get(dev, "dc", GPIOD_OUT_LOW); if (IS_ERR(dc)) { DRM_DEV_ERROR(dev, "Failed to get gpio 'dc'\n"); return PTR_ERR(dc); } mipi->backlight = devm_of_find_backlight(dev); if (IS_ERR(mipi->backlight)) return PTR_ERR(mipi->backlight); device_property_read_u32(dev, "rotation", &rotation); ret = mipi_dbi_spi_init(spi, mipi, dc); if (ret) return ret; /* Cannot read from Adafruit 1.8" display via SPI */ mipi->read_commands = NULL; ret = mipi_dbi_init(&spi->dev, mipi, &jd_t18003_t01_pipe_funcs, &st7735r_driver, &jd_t18003_t01_mode, rotation); if (ret) return ret; spi_set_drvdata(spi, mipi); return devm_tinydrm_register(&mipi->tinydrm); }
static struct drm_framebuffer * rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd) { struct drm_framebuffer *fb; struct drm_gem_object *objs[ROCKCHIP_MAX_FB_BUFFER]; struct drm_gem_object *obj; unsigned int hsub; unsigned int vsub; int num_planes; int ret; int i; hsub = drm_format_horz_chroma_subsampling(mode_cmd->pixel_format); vsub = drm_format_vert_chroma_subsampling(mode_cmd->pixel_format); num_planes = min(drm_format_num_planes(mode_cmd->pixel_format), ROCKCHIP_MAX_FB_BUFFER); for (i = 0; i < num_planes; i++) { unsigned int width = mode_cmd->width / (i ? hsub : 1); unsigned int height = mode_cmd->height / (i ? vsub : 1); unsigned int min_size; obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[i]); if (!obj) { DRM_DEV_ERROR(dev->dev, "Failed to lookup GEM object\n"); ret = -ENXIO; goto err_gem_object_unreference; } min_size = (height - 1) * mode_cmd->pitches[i] + mode_cmd->offsets[i] + width * drm_format_plane_cpp(mode_cmd->pixel_format, i); if (obj->size < min_size) { drm_gem_object_put_unlocked(obj); ret = -EINVAL; goto err_gem_object_unreference; } objs[i] = obj; } fb = rockchip_fb_alloc(dev, mode_cmd, objs, i); if (IS_ERR(fb)) { ret = PTR_ERR(fb); goto err_gem_object_unreference; } return fb; err_gem_object_unreference: for (i--; i >= 0; i--) drm_gem_object_put_unlocked(objs[i]); return ERR_PTR(ret); }
static int hx8357d_probe(struct spi_device *spi) { struct device *dev = &spi->dev; struct drm_device *drm; struct mipi_dbi *mipi; struct gpio_desc *dc; u32 rotation = 0; int ret; mipi = kzalloc(sizeof(*mipi), GFP_KERNEL); if (!mipi) return -ENOMEM; drm = &mipi->drm; ret = devm_drm_dev_init(dev, drm, &hx8357d_driver); if (ret) { kfree(mipi); return ret; } drm_mode_config_init(drm); dc = devm_gpiod_get(dev, "dc", GPIOD_OUT_LOW); if (IS_ERR(dc)) { DRM_DEV_ERROR(dev, "Failed to get gpio 'dc'\n"); return PTR_ERR(dc); } mipi->backlight = devm_of_find_backlight(dev); if (IS_ERR(mipi->backlight)) return PTR_ERR(mipi->backlight); device_property_read_u32(dev, "rotation", &rotation); ret = mipi_dbi_spi_init(spi, mipi, dc); if (ret) return ret; ret = mipi_dbi_init(mipi, &hx8357d_pipe_funcs, &yx350hv15_mode, rotation); if (ret) return ret; drm_mode_config_reset(drm); ret = drm_dev_register(drm, 0); if (ret) return ret; spi_set_drvdata(spi, drm); drm_fbdev_generic_setup(drm, 0); return 0; }
static void __iomem *a6xx_gmu_get_mmio(struct platform_device *pdev, const char *name) { void __iomem *ret; struct resource *res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); if (!res) { DRM_DEV_ERROR(&pdev->dev, "Unable to find the %s registers\n", name); return ERR_PTR(-EINVAL); } ret = ioremap(res->start, resource_size(res)); if (!ret) { DRM_DEV_ERROR(&pdev->dev, "Unable to map the %s registers\n", name); return ERR_PTR(-EINVAL); } return ret; }
static int dw_mipi_dsi_dcs_long_write(struct dw_mipi_dsi *dsi, const struct mipi_dsi_msg *msg) { const u8 *tx_buf = msg->tx_buf; int len = msg->tx_len, pld_data_bytes = sizeof(u32), ret; u32 hdr_val = GEN_HDATA(msg->tx_len) | GEN_HTYPE(msg->type); u32 remainder; u32 val; if (msg->tx_len < 3) { DRM_DEV_ERROR(dsi->dev, "wrong tx buf length %zu for long write\n", msg->tx_len); return -EINVAL; } while (DIV_ROUND_UP(len, pld_data_bytes)) { if (len < pld_data_bytes) { remainder = 0; memcpy(&remainder, tx_buf, len); dsi_write(dsi, DSI_GEN_PLD_DATA, remainder); len = 0; } else { memcpy(&remainder, tx_buf, pld_data_bytes); dsi_write(dsi, DSI_GEN_PLD_DATA, remainder); tx_buf += pld_data_bytes; len -= pld_data_bytes; } ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS, val, !(val & GEN_PLD_W_FULL), 1000, CMD_PKT_STATUS_TIMEOUT_US); if (ret < 0) { DRM_DEV_ERROR(dsi->dev, "failed to get available write payload FIFO\n"); return ret; } } return dw_mipi_dsi_gen_pkt_hdr_write(dsi, hdr_val); }
static int a6xx_gmu_hfi_start(struct a6xx_gmu *gmu) { u32 val; int ret; gmu_write(gmu, REG_A6XX_GMU_HFI_CTRL_INIT, 1); ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_HFI_CTRL_STATUS, val, val & 1, 100, 10000); if (ret) DRM_DEV_ERROR(gmu->dev, "Unable to start the HFI queues\n"); return ret; }
static void a6xx_rpmh_stop(struct a6xx_gmu *gmu) { int ret; u32 val; gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 1); ret = gmu_poll_timeout(gmu, REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0, val, val & (1 << 16), 100, 10000); if (ret) DRM_DEV_ERROR(gmu->dev, "Unable to power off the GPU RSC\n"); gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 0); }
/* * Note: * CTL registers need to be flushed after calling this function * (call mdp5_ctl_commit() with mdp_ctl_flush_mask_ctl() mask) */ int mdp5_ctl_set_cursor(struct mdp5_ctl *ctl, struct mdp5_pipeline *pipeline, int cursor_id, bool enable) { struct mdp5_ctl_manager *ctl_mgr = ctl->ctlm; unsigned long flags; u32 blend_cfg; struct mdp5_hw_mixer *mixer = pipeline->mixer; if (unlikely(WARN_ON(!mixer))) { DRM_DEV_ERROR(ctl_mgr->dev->dev, "CTL %d cannot find LM", ctl->id); return -EINVAL; } if (pipeline->r_mixer) { DRM_DEV_ERROR(ctl_mgr->dev->dev, "unsupported configuration"); return -EINVAL; } spin_lock_irqsave(&ctl->hw_lock, flags); blend_cfg = ctl_read(ctl, REG_MDP5_CTL_LAYER_REG(ctl->id, mixer->lm)); if (enable) blend_cfg |= MDP5_CTL_LAYER_REG_CURSOR_OUT; else blend_cfg &= ~MDP5_CTL_LAYER_REG_CURSOR_OUT; ctl_write(ctl, REG_MDP5_CTL_LAYER_REG(ctl->id, mixer->lm), blend_cfg); ctl->cursor_on = enable; spin_unlock_irqrestore(&ctl->hw_lock, flags); ctl->pending_ctl_trigger = mdp_ctl_flush_mask_cursor(cursor_id); return 0; }
static int mdp5_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor) { struct drm_device *dev = minor->dev; int ret; ret = drm_debugfs_create_files(mdp5_debugfs_list, ARRAY_SIZE(mdp5_debugfs_list), minor->debugfs_root, minor); if (ret) { DRM_DEV_ERROR(dev->dev, "could not install mdp5_debugfs_list\n"); return ret; } return 0; }
static int get_clk(struct platform_device *pdev, struct clk **clkp, const char *name, bool mandatory) { struct device *dev = &pdev->dev; struct clk *clk = msm_clk_get(pdev, name); if (IS_ERR(clk) && mandatory) { DRM_DEV_ERROR(dev, "failed to get %s (%ld)\n", name, PTR_ERR(clk)); return PTR_ERR(clk); } if (IS_ERR(clk)) DBG("skipping %s", name); else *clkp = clk; return 0; }
static int a6xx_gmu_start(struct a6xx_gmu *gmu) { int ret; u32 val; gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 1); gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 0); ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_CM3_FW_INIT_RESULT, val, val == 0xbabeface, 100, 10000); if (ret) DRM_DEV_ERROR(gmu->dev, "GMU firmware initialization timed out\n"); return ret; }
static void bs_init(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder) { struct drm_device *dev = mdp4_lcdc_encoder->base.dev; struct lcdc_platform_data *lcdc_pdata = mdp4_find_pdata("lvds.0"); if (!lcdc_pdata) { DRM_DEV_ERROR(dev->dev, "could not find lvds pdata\n"); return; } if (lcdc_pdata->bus_scale_table) { mdp4_lcdc_encoder->bsc = msm_bus_scale_register_client( lcdc_pdata->bus_scale_table); DBG("lvds : bus scale client: %08x", mdp4_lcdc_encoder->bsc); } }