Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm: sti: add Compositor

Compositor control all the input sub-device (VID, GDP)
and the mixer(s).
It is the main entry point for composition.
Layer interface is used to control the abstracted layers.

Add debug in mixer and GDP.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
Reviewed-by: Rob Clark <robdclark@gmail.com>

+566 -1
+1
drivers/gpu/drm/sti/Kconfig
··· 1 1 config DRM_STI 2 2 tristate "DRM Support for STMicroelectronics SoC stiH41x Series" 3 3 depends on DRM && (SOC_STIH415 || SOC_STIH416 || ARCH_MULTIPLATFORM) 4 + select DRM_KMS_CMA_HELPER 4 5 help 5 6 Choose this option to enable DRM on STM stiH41x chipset
+3 -1
drivers/gpu/drm/sti/Makefile
··· 1 1 sticompositor-y := \ 2 + sti_layer.o \ 2 3 sti_mixer.o \ 3 4 sti_gdp.o \ 4 - sti_vid.o 5 + sti_vid.o \ 6 + sti_compositor.o 5 7 6 8 stihdmi-y := sti_hdmi.o \ 7 9 sti_hdmi_tx3g0c55phy.o \
+236
drivers/gpu/drm/sti/sti_compositor.c
··· 1 + /* 2 + * Copyright (C) STMicroelectronics SA 2014 3 + * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> 4 + * Fabien Dessenne <fabien.dessenne@st.com> 5 + * for STMicroelectronics. 6 + * License terms: GNU General Public License (GPL), version 2 7 + */ 8 + 9 + #include <linux/component.h> 10 + #include <linux/module.h> 11 + #include <linux/platform_device.h> 12 + #include <linux/reset.h> 13 + 14 + #include <drm/drmP.h> 15 + 16 + #include "sti_compositor.h" 17 + #include "sti_gdp.h" 18 + #include "sti_vtg.h" 19 + 20 + /* 21 + * stiH407 compositor properties 22 + */ 23 + struct sti_compositor_data stih407_compositor_data = { 24 + .nb_subdev = 6, 25 + .subdev_desc = { 26 + {STI_GPD_SUBDEV, (int)STI_GDP_0, 0x100}, 27 + {STI_GPD_SUBDEV, (int)STI_GDP_1, 0x200}, 28 + {STI_GPD_SUBDEV, (int)STI_GDP_2, 0x300}, 29 + {STI_GPD_SUBDEV, (int)STI_GDP_3, 0x400}, 30 + {STI_VID_SUBDEV, (int)STI_VID_0, 0x700}, 31 + {STI_MIXER_MAIN_SUBDEV, STI_MIXER_MAIN, 0xC00} 32 + }, 33 + }; 34 + 35 + /* 36 + * stiH416 compositor properties 37 + * Note: 38 + * on stih416 MIXER_AUX has a different base address from MIXER_MAIN 39 + * Moreover, GDPx is different for Main and Aux Mixer. So this subdev map does 40 + * not fit for stiH416 if we want to enable the MIXER_AUX. 41 + */ 42 + struct sti_compositor_data stih416_compositor_data = { 43 + .nb_subdev = 3, 44 + .subdev_desc = { 45 + {STI_GPD_SUBDEV, (int)STI_GDP_0, 0x100}, 46 + {STI_GPD_SUBDEV, (int)STI_GDP_1, 0x200}, 47 + {STI_MIXER_MAIN_SUBDEV, STI_MIXER_MAIN, 0xC00} 48 + }, 49 + }; 50 + 51 + static int sti_compositor_init_subdev(struct sti_compositor *compo, 52 + struct sti_compositor_subdev_descriptor *desc, 53 + unsigned int array_size) 54 + { 55 + unsigned int i, mixer_id = 0, layer_id = 0; 56 + 57 + for (i = 0; i < array_size; i++) { 58 + switch (desc[i].type) { 59 + case STI_MIXER_MAIN_SUBDEV: 60 + case STI_MIXER_AUX_SUBDEV: 61 + compo->mixer[mixer_id++] = 62 + sti_mixer_create(compo->dev, desc[i].id, 63 + compo->regs + desc[i].offset); 64 + break; 65 + case STI_GPD_SUBDEV: 66 + case STI_VID_SUBDEV: 67 + compo->layer[layer_id++] = 68 + sti_layer_create(compo->dev, desc[i].id, 69 + compo->regs + desc[i].offset); 70 + break; 71 + /* case STI_CURSOR_SUBDEV : TODO */ 72 + default: 73 + DRM_ERROR("Unknow subdev compoment type\n"); 74 + return 1; 75 + } 76 + 77 + } 78 + compo->nb_mixers = mixer_id; 79 + compo->nb_layers = layer_id; 80 + 81 + return 0; 82 + } 83 + 84 + static int sti_compositor_bind(struct device *dev, struct device *master, 85 + void *data) 86 + { 87 + struct sti_compositor *compo = dev_get_drvdata(dev); 88 + struct drm_device *drm_dev = data; 89 + unsigned int i, crtc = 0, plane = 0; 90 + 91 + drm_vblank_init(drm_dev, crtc); 92 + /* Allow usage of vblank without having to call drm_irq_install */ 93 + drm_dev->irq_enabled = 1; 94 + 95 + 96 + DRM_DEBUG_DRIVER("Initialized %d DRM CRTC(s) and %d DRM plane(s)\n", 97 + crtc, plane); 98 + DRM_DEBUG_DRIVER("DRM plane(s) for VID/VDP not created yet\n"); 99 + 100 + return 0; 101 + } 102 + 103 + static void sti_compositor_unbind(struct device *dev, struct device *master, 104 + void *data) 105 + { 106 + /* do nothing */ 107 + } 108 + 109 + static const struct component_ops sti_compositor_ops = { 110 + .bind = sti_compositor_bind, 111 + .unbind = sti_compositor_unbind, 112 + }; 113 + 114 + static const struct of_device_id compositor_of_match[] = { 115 + { 116 + .compatible = "st,stih416-compositor", 117 + .data = &stih416_compositor_data, 118 + }, { 119 + .compatible = "st,stih407-compositor", 120 + .data = &stih407_compositor_data, 121 + }, { 122 + /* end node */ 123 + } 124 + }; 125 + MODULE_DEVICE_TABLE(of, compositor_of_match); 126 + 127 + static int sti_compositor_probe(struct platform_device *pdev) 128 + { 129 + struct device *dev = &pdev->dev; 130 + struct device_node *np = dev->of_node; 131 + struct device_node *vtg_np; 132 + struct sti_compositor *compo; 133 + struct resource *res; 134 + int err; 135 + 136 + compo = devm_kzalloc(dev, sizeof(*compo), GFP_KERNEL); 137 + if (!compo) { 138 + DRM_ERROR("Failed to allocate compositor context\n"); 139 + return -ENOMEM; 140 + } 141 + compo->dev = dev; 142 + 143 + /* populate data structure depending on compatibility */ 144 + BUG_ON(!of_match_node(compositor_of_match, np)->data); 145 + 146 + memcpy(&compo->data, of_match_node(compositor_of_match, np)->data, 147 + sizeof(struct sti_compositor_data)); 148 + 149 + /* Get Memory ressources */ 150 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 151 + if (res == NULL) { 152 + DRM_ERROR("Get memory resource failed\n"); 153 + return -ENXIO; 154 + } 155 + compo->regs = devm_ioremap(dev, res->start, resource_size(res)); 156 + if (compo->regs == NULL) { 157 + DRM_ERROR("Register mapping failed\n"); 158 + return -ENXIO; 159 + } 160 + 161 + /* Get clock resources */ 162 + compo->clk_compo_main = devm_clk_get(dev, "compo_main"); 163 + if (IS_ERR(compo->clk_compo_main)) { 164 + DRM_ERROR("Cannot get compo_main clock\n"); 165 + return PTR_ERR(compo->clk_compo_main); 166 + } 167 + 168 + compo->clk_compo_aux = devm_clk_get(dev, "compo_aux"); 169 + if (IS_ERR(compo->clk_compo_aux)) { 170 + DRM_ERROR("Cannot get compo_aux clock\n"); 171 + return PTR_ERR(compo->clk_compo_aux); 172 + } 173 + 174 + compo->clk_pix_main = devm_clk_get(dev, "pix_main"); 175 + if (IS_ERR(compo->clk_pix_main)) { 176 + DRM_ERROR("Cannot get pix_main clock\n"); 177 + return PTR_ERR(compo->clk_pix_main); 178 + } 179 + 180 + compo->clk_pix_aux = devm_clk_get(dev, "pix_aux"); 181 + if (IS_ERR(compo->clk_pix_aux)) { 182 + DRM_ERROR("Cannot get pix_aux clock\n"); 183 + return PTR_ERR(compo->clk_pix_aux); 184 + } 185 + 186 + /* Get reset resources */ 187 + compo->rst_main = devm_reset_control_get(dev, "compo-main"); 188 + /* Take compo main out of reset */ 189 + if (!IS_ERR(compo->rst_main)) 190 + reset_control_deassert(compo->rst_main); 191 + 192 + compo->rst_aux = devm_reset_control_get(dev, "compo-aux"); 193 + /* Take compo aux out of reset */ 194 + if (!IS_ERR(compo->rst_aux)) 195 + reset_control_deassert(compo->rst_aux); 196 + 197 + vtg_np = of_parse_phandle(pdev->dev.of_node, "st,vtg", 0); 198 + if (vtg_np) 199 + compo->vtg_main = of_vtg_find(vtg_np); 200 + 201 + vtg_np = of_parse_phandle(pdev->dev.of_node, "st,vtg", 1); 202 + if (vtg_np) 203 + compo->vtg_aux = of_vtg_find(vtg_np); 204 + 205 + /* Initialize compositor subdevices */ 206 + err = sti_compositor_init_subdev(compo, compo->data.subdev_desc, 207 + compo->data.nb_subdev); 208 + if (err) 209 + return err; 210 + 211 + platform_set_drvdata(pdev, compo); 212 + 213 + return component_add(&pdev->dev, &sti_compositor_ops); 214 + } 215 + 216 + static int sti_compositor_remove(struct platform_device *pdev) 217 + { 218 + component_del(&pdev->dev, &sti_compositor_ops); 219 + return 0; 220 + } 221 + 222 + static struct platform_driver sti_compositor_driver = { 223 + .driver = { 224 + .name = "sti-compositor", 225 + .owner = THIS_MODULE, 226 + .of_match_table = compositor_of_match, 227 + }, 228 + .probe = sti_compositor_probe, 229 + .remove = sti_compositor_remove, 230 + }; 231 + 232 + module_platform_driver(sti_compositor_driver); 233 + 234 + MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>"); 235 + MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver"); 236 + MODULE_LICENSE("GPL");
+90
drivers/gpu/drm/sti/sti_compositor.h
··· 1 + /* 2 + * Copyright (C) STMicroelectronics SA 2014 3 + * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> 4 + * Fabien Dessenne <fabien.dessenne@st.com> 5 + * for STMicroelectronics. 6 + * License terms: GNU General Public License (GPL), version 2 7 + */ 8 + 9 + #ifndef _STI_COMPOSITOR_H_ 10 + #define _STI_COMPOSITOR_H_ 11 + 12 + #include <linux/clk.h> 13 + #include <linux/kernel.h> 14 + 15 + #include "sti_layer.h" 16 + #include "sti_mixer.h" 17 + 18 + #define WAIT_NEXT_VSYNC_MS 50 /*ms*/ 19 + 20 + #define STI_MAX_LAYER 8 21 + #define STI_MAX_MIXER 2 22 + 23 + enum sti_compositor_subdev_type { 24 + STI_MIXER_MAIN_SUBDEV, 25 + STI_MIXER_AUX_SUBDEV, 26 + STI_GPD_SUBDEV, 27 + STI_VID_SUBDEV, 28 + STI_CURSOR_SUBDEV, 29 + }; 30 + 31 + struct sti_compositor_subdev_descriptor { 32 + enum sti_compositor_subdev_type type; 33 + int id; 34 + unsigned int offset; 35 + }; 36 + 37 + /** 38 + * STI Compositor data structure 39 + * 40 + * @nb_subdev: number of subdevices supported by the compositor 41 + * @subdev_desc: subdev list description 42 + */ 43 + #define MAX_SUBDEV 9 44 + struct sti_compositor_data { 45 + unsigned int nb_subdev; 46 + struct sti_compositor_subdev_descriptor subdev_desc[MAX_SUBDEV]; 47 + }; 48 + 49 + /** 50 + * STI Compositor structure 51 + * 52 + * @dev: driver device 53 + * @regs: registers (main) 54 + * @data: device data 55 + * @clk_compo_main: clock for main compo 56 + * @clk_compo_aux: clock for aux compo 57 + * @clk_pix_main: pixel clock for main path 58 + * @clk_pix_aux: pixel clock for aux path 59 + * @rst_main: reset control of the main path 60 + * @rst_aux: reset control of the aux path 61 + * @mixer: array of mixers 62 + * @vtg_main: vtg for main data path 63 + * @vtg_aux: vtg for auxillary data path 64 + * @layer: array of layers 65 + * @nb_mixers: number of mixers for this compositor 66 + * @nb_layers: number of layers (GDP,VID,...) for this compositor 67 + * @enable: true if compositor is enable else false 68 + * @vtg_vblank_nb: callback for VTG VSYNC notification 69 + */ 70 + struct sti_compositor { 71 + struct device *dev; 72 + void __iomem *regs; 73 + struct sti_compositor_data data; 74 + struct clk *clk_compo_main; 75 + struct clk *clk_compo_aux; 76 + struct clk *clk_pix_main; 77 + struct clk *clk_pix_aux; 78 + struct reset_control *rst_main; 79 + struct reset_control *rst_aux; 80 + struct sti_mixer *mixer[STI_MAX_MIXER]; 81 + struct sti_vtg *vtg_main; 82 + struct sti_vtg *vtg_aux; 83 + struct sti_layer *layer[STI_MAX_LAYER]; 84 + int nb_mixers; 85 + int nb_layers; 86 + bool enable; 87 + struct notifier_block vtg_vblank_nb; 88 + }; 89 + 90 + #endif
+33
drivers/gpu/drm/sti/sti_gdp.c
··· 9 9 #include <linux/clk.h> 10 10 #include <linux/dma-mapping.h> 11 11 12 + #include "sti_compositor.h" 12 13 #include "sti_gdp.h" 13 14 #include "sti_layer.h" 14 15 #include "sti_vtg.h" ··· 183 182 (virt_nvn != gdp->node_list[i].top_field)) 184 183 return &gdp->node_list[i]; 185 184 185 + /* in hazardious cases restart with the first node */ 186 + DRM_ERROR("inconsistent NVN for %s: 0x%08X\n", 187 + sti_layer_to_str(layer), hw_nvn); 188 + 186 189 end: 187 190 return &gdp->node_list[0]; 188 191 } ··· 220 215 return &gdp->node_list[i]; 221 216 222 217 end: 218 + DRM_DEBUG_DRIVER("Warning, NVN 0x%08X for %s does not match any node\n", 219 + hw_nvn, sti_layer_to_str(layer)); 220 + 223 221 return NULL; 224 222 } 225 223 ··· 243 235 struct drm_display_mode *mode = layer->mode; 244 236 struct device *dev = layer->dev; 245 237 struct sti_gdp *gdp = to_sti_gdp(layer); 238 + struct sti_compositor *compo = dev_get_drvdata(dev); 246 239 int format; 247 240 unsigned int depth, bpp; 248 241 int rate = mode->clock * 1000; ··· 253 244 list = sti_gdp_get_free_nodes(layer); 254 245 top_field = list->top_field; 255 246 btm_field = list->btm_field; 247 + 248 + dev_dbg(dev, "%s %s top_node:0x%p btm_node:0x%p\n", __func__, 249 + sti_layer_to_str(layer), top_field, btm_field); 256 250 257 251 /* Build the top field from layer params */ 258 252 top_field->gam_gdp_agc = GAM_GDP_AGC_FULL_RANGE; ··· 301 289 layer->pitches[0]; 302 290 303 291 if (first_prepare) { 292 + /* Register gdp callback */ 293 + if (sti_vtg_register_client(layer->mixer_id == STI_MIXER_MAIN ? 294 + compo->vtg_main : compo->vtg_aux, 295 + &gdp->vtg_field_nb, layer->mixer_id)) { 296 + DRM_ERROR("Cannot register VTG notifier\n"); 297 + return 1; 298 + } 299 + 304 300 /* Set and enable gdp clock */ 305 301 if (gdp->clk_pix) { 306 302 res = clk_set_rate(gdp->clk_pix, rate); ··· 353 333 u32 dma_updated_btm = virt_to_dma(layer->dev, updated_btm_node); 354 334 struct sti_gdp_node_list *curr_list = sti_gdp_get_current_nodes(layer); 355 335 336 + dev_dbg(layer->dev, "%s %s top/btm_node:0x%p/0x%p\n", __func__, 337 + sti_layer_to_str(layer), 338 + updated_top_node, updated_btm_node); 356 339 dev_dbg(layer->dev, "Current NVN:0x%X\n", 357 340 readl(layer->regs + GAM_GDP_NVN_OFFSET)); 358 341 dev_dbg(layer->dev, "Posted buff: %lx current buff: %x\n", ··· 365 342 if (curr_list == NULL) { 366 343 /* First update or invalid node should directly write in the 367 344 * hw register */ 345 + DRM_DEBUG_DRIVER("%s first update (or invalid node)", 346 + sti_layer_to_str(layer)); 347 + 368 348 writel(gdp->is_curr_top == true ? 369 349 dma_updated_btm : dma_updated_top, 370 350 layer->regs + GAM_GDP_NVN_OFFSET); ··· 406 380 { 407 381 unsigned int i; 408 382 struct sti_gdp *gdp = to_sti_gdp(layer); 383 + struct sti_compositor *compo = dev_get_drvdata(layer->dev); 384 + 385 + DRM_DEBUG_DRIVER("%s\n", sti_layer_to_str(layer)); 409 386 410 387 /* Set the nodes as 'to be ignored on mixer' */ 411 388 for (i = 0; i < GDP_NODE_NB_BANK; i++) { 412 389 gdp->node_list[i].top_field->gam_gdp_ppt |= GAM_GDP_PPT_IGNORE; 413 390 gdp->node_list[i].btm_field->gam_gdp_ppt |= GAM_GDP_PPT_IGNORE; 414 391 } 392 + 393 + if (sti_vtg_unregister_client(layer->mixer_id == STI_MIXER_MAIN ? 394 + compo->vtg_main : compo->vtg_aux, &gdp->vtg_field_nb)) 395 + DRM_DEBUG_DRIVER("Warning: cannot unregister VTG notifier\n"); 415 396 416 397 if (gdp->clk_pix) 417 398 clk_disable_unprepare(gdp->clk_pix);
+197
drivers/gpu/drm/sti/sti_layer.c
··· 1 + /* 2 + * Copyright (C) STMicroelectronics SA 2014 3 + * Authors: Benjamin Gaignard <benjamin.gaignard@st.com> 4 + * Fabien Dessenne <fabien.dessenne@st.com> 5 + * for STMicroelectronics. 6 + * License terms: GNU General Public License (GPL), version 2 7 + */ 8 + 9 + #include <drm/drmP.h> 10 + #include <drm/drm_gem_cma_helper.h> 11 + #include <drm/drm_fb_cma_helper.h> 12 + 13 + #include "sti_compositor.h" 14 + #include "sti_gdp.h" 15 + #include "sti_layer.h" 16 + #include "sti_vid.h" 17 + 18 + const char *sti_layer_to_str(struct sti_layer *layer) 19 + { 20 + switch (layer->desc) { 21 + case STI_GDP_0: 22 + return "GDP0"; 23 + case STI_GDP_1: 24 + return "GDP1"; 25 + case STI_GDP_2: 26 + return "GDP2"; 27 + case STI_GDP_3: 28 + return "GDP3"; 29 + case STI_VID_0: 30 + return "VID0"; 31 + case STI_VID_1: 32 + return "VID1"; 33 + case STI_CURSOR: 34 + return "CURSOR"; 35 + default: 36 + return "<UNKNOWN LAYER>"; 37 + } 38 + } 39 + 40 + struct sti_layer *sti_layer_create(struct device *dev, int desc, 41 + void __iomem *baseaddr) 42 + { 43 + 44 + struct sti_layer *layer = NULL; 45 + 46 + switch (desc & STI_LAYER_TYPE_MASK) { 47 + case STI_GDP: 48 + layer = sti_gdp_create(dev, desc); 49 + break; 50 + case STI_VID: 51 + layer = sti_vid_create(dev); 52 + break; 53 + } 54 + 55 + if (!layer) { 56 + DRM_ERROR("Failed to create layer\n"); 57 + return NULL; 58 + } 59 + 60 + layer->desc = desc; 61 + layer->dev = dev; 62 + layer->regs = baseaddr; 63 + 64 + layer->ops->init(layer); 65 + 66 + DRM_DEBUG_DRIVER("%s created\n", sti_layer_to_str(layer)); 67 + 68 + return layer; 69 + } 70 + 71 + int sti_layer_prepare(struct sti_layer *layer, struct drm_framebuffer *fb, 72 + struct drm_display_mode *mode, int mixer_id, 73 + int dest_x, int dest_y, int dest_w, int dest_h, 74 + int src_x, int src_y, int src_w, int src_h) 75 + { 76 + int ret; 77 + unsigned int i; 78 + struct drm_gem_cma_object *cma_obj; 79 + 80 + if (!layer || !fb || !mode) { 81 + DRM_ERROR("Null fb, layer or mode\n"); 82 + return 1; 83 + } 84 + 85 + cma_obj = drm_fb_cma_get_gem_obj(fb, 0); 86 + if (!cma_obj) { 87 + DRM_ERROR("Can't get CMA GEM object for fb\n"); 88 + return 1; 89 + } 90 + 91 + layer->fb = fb; 92 + layer->mode = mode; 93 + layer->mixer_id = mixer_id; 94 + layer->dst_x = dest_x; 95 + layer->dst_y = dest_y; 96 + layer->dst_w = clamp_val(dest_w, 0, mode->crtc_hdisplay - dest_x); 97 + layer->dst_h = clamp_val(dest_h, 0, mode->crtc_vdisplay - dest_y); 98 + layer->src_x = src_x; 99 + layer->src_y = src_y; 100 + layer->src_w = src_w; 101 + layer->src_h = src_h; 102 + layer->format = fb->pixel_format; 103 + layer->paddr = cma_obj->paddr; 104 + for (i = 0; i < 4; i++) { 105 + layer->pitches[i] = fb->pitches[i]; 106 + layer->offsets[i] = fb->offsets[i]; 107 + } 108 + 109 + DRM_DEBUG_DRIVER("%s is associated with mixer_id %d\n", 110 + sti_layer_to_str(layer), 111 + layer->mixer_id); 112 + DRM_DEBUG_DRIVER("%s dst=(%dx%d)@(%d,%d) - src=(%dx%d)@(%d,%d)\n", 113 + sti_layer_to_str(layer), 114 + layer->dst_w, layer->dst_h, layer->dst_x, layer->dst_y, 115 + layer->src_w, layer->src_h, layer->src_x, 116 + layer->src_y); 117 + 118 + DRM_DEBUG_DRIVER("drm FB:%d format:%.4s phys@:0x%lx\n", fb->base.id, 119 + (char *)&layer->format, (unsigned long)layer->paddr); 120 + 121 + if (!layer->ops->prepare) 122 + goto err_no_prepare; 123 + 124 + ret = layer->ops->prepare(layer, !layer->enabled); 125 + if (!ret) 126 + layer->enabled = true; 127 + 128 + return ret; 129 + 130 + err_no_prepare: 131 + DRM_ERROR("Cannot prepare\n"); 132 + return 1; 133 + } 134 + 135 + int sti_layer_commit(struct sti_layer *layer) 136 + { 137 + if (!layer) 138 + return 1; 139 + 140 + if (!layer->ops->commit) 141 + goto err_no_commit; 142 + 143 + return layer->ops->commit(layer); 144 + 145 + err_no_commit: 146 + DRM_ERROR("Cannot commit\n"); 147 + return 1; 148 + } 149 + 150 + int sti_layer_disable(struct sti_layer *layer) 151 + { 152 + int ret; 153 + 154 + DRM_DEBUG_DRIVER("%s\n", sti_layer_to_str(layer)); 155 + if (!layer) 156 + return 1; 157 + 158 + if (!layer->enabled) 159 + return 0; 160 + 161 + if (!layer->ops->disable) 162 + goto err_no_disable; 163 + 164 + ret = layer->ops->disable(layer); 165 + if (!ret) 166 + layer->enabled = false; 167 + else 168 + DRM_ERROR("Disable failed\n"); 169 + 170 + return ret; 171 + 172 + err_no_disable: 173 + DRM_ERROR("Cannot disable\n"); 174 + return 1; 175 + } 176 + 177 + const uint32_t *sti_layer_get_formats(struct sti_layer *layer) 178 + { 179 + if (!layer) 180 + return NULL; 181 + 182 + if (!layer->ops->get_formats) 183 + return NULL; 184 + 185 + return layer->ops->get_formats(layer); 186 + } 187 + 188 + unsigned int sti_layer_get_nb_formats(struct sti_layer *layer) 189 + { 190 + if (!layer) 191 + return 0; 192 + 193 + if (!layer->ops->get_nb_formats) 194 + return 0; 195 + 196 + return layer->ops->get_nb_formats(layer); 197 + }
+6
drivers/gpu/drm/sti/sti_mixer.c
··· 6 6 * License terms: GNU General Public License (GPL), version 2 7 7 */ 8 8 9 + #include "sti_compositor.h" 9 10 #include "sti_mixer.h" 10 11 #include "sti_vtg.h" 11 12 ··· 134 133 mask = GAM_DEPTH_MASK_ID << (3 * depth); 135 134 layer_id = layer_id << (3 * depth); 136 135 136 + DRM_DEBUG_DRIVER("%s %s depth=%d\n", sti_mixer_to_str(mixer), 137 + sti_layer_to_str(layer), depth); 137 138 dev_dbg(mixer->dev, "GAM_MIXER_CRB val 0x%x mask 0x%x\n", 138 139 layer_id, mask); 139 140 ··· 197 194 struct sti_layer *layer, bool status) 198 195 { 199 196 u32 mask, val; 197 + 198 + DRM_DEBUG_DRIVER("%s %s %s\n", status ? "enable" : "disable", 199 + sti_mixer_to_str(mixer), sti_layer_to_str(layer)); 200 200 201 201 mask = sti_mixer_get_layer_mask(layer); 202 202 if (!mask) {