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

Configure Feed

Select the types of activity you want to include in your feed.

drm: atmel-hlcdc: add driver ops to differentiate HLCDC and XLCDC IP

Add LCD IP specific ops in driver data to differentiate
HLCDC and XLCDC code within the atmel-hlcdc driver files.
XLCDC in SAM9X7 has different sets of registers and additional
configuration bits when compared to previous HLCDC IP. Read/write
operation on the controller register and functionality is now
separated using the LCD IP specific ops.

Signed-off-by: Manikandan Muralidharan <manikandan.m@microchip.com>
Acked-by: Sam Ravnborg <sam@ravnborg.org>
Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20240424053351.589830-2-manikandan.m@microchip.com

authored by

Manikandan Muralidharan and committed by
Sam Ravnborg
aa71584b 0c02cebc

+183 -94
+5
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
··· 58 58 .conflicting_output_formats = true, 59 59 .nlayers = ARRAY_SIZE(atmel_hlcdc_at91sam9n12_layers), 60 60 .layers = atmel_hlcdc_at91sam9n12_layers, 61 + .ops = &atmel_hlcdc_ops, 61 62 }; 62 63 63 64 static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = { ··· 152 151 .conflicting_output_formats = true, 153 152 .nlayers = ARRAY_SIZE(atmel_hlcdc_at91sam9x5_layers), 154 153 .layers = atmel_hlcdc_at91sam9x5_layers, 154 + .ops = &atmel_hlcdc_ops, 155 155 }; 156 156 157 157 static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = { ··· 271 269 .conflicting_output_formats = true, 272 270 .nlayers = ARRAY_SIZE(atmel_hlcdc_sama5d3_layers), 273 271 .layers = atmel_hlcdc_sama5d3_layers, 272 + .ops = &atmel_hlcdc_ops, 274 273 }; 275 274 276 275 static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = { ··· 367 364 .max_hpw = 0x3ff, 368 365 .nlayers = ARRAY_SIZE(atmel_hlcdc_sama5d4_layers), 369 366 .layers = atmel_hlcdc_sama5d4_layers, 367 + .ops = &atmel_hlcdc_ops, 370 368 }; 371 369 372 370 static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sam9x60_layers[] = { ··· 464 460 .fixed_clksrc = true, 465 461 .nlayers = ARRAY_SIZE(atmel_hlcdc_sam9x60_layers), 466 462 .layers = atmel_hlcdc_sam9x60_layers, 463 + .ops = &atmel_hlcdc_ops, 467 464 }; 468 465 469 466 static const struct of_device_id atmel_hlcdc_of_match[] = {
+59 -24
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
··· 289 289 } 290 290 291 291 /** 292 + * struct atmel_hlcdc_dc - Atmel HLCDC Display Controller. 293 + * @desc: HLCDC Display Controller description 294 + * @dscrpool: DMA coherent pool used to allocate DMA descriptors 295 + * @hlcdc: pointer to the atmel_hlcdc structure provided by the MFD device 296 + * @crtc: CRTC provided by the display controller 297 + * @layers: active HLCDC layers 298 + * @suspend: used to store the HLCDC state when entering suspend 299 + * @suspend.imr: used to read/write LCDC Interrupt Mask Register 300 + * @suspend.state: Atomic commit structure 301 + */ 302 + struct atmel_hlcdc_dc { 303 + const struct atmel_hlcdc_dc_desc *desc; 304 + struct dma_pool *dscrpool; 305 + struct atmel_hlcdc *hlcdc; 306 + struct drm_crtc *crtc; 307 + struct atmel_hlcdc_layer *layers[ATMEL_HLCDC_MAX_LAYERS]; 308 + struct { 309 + u32 imr; 310 + struct drm_atomic_state *state; 311 + } suspend; 312 + }; 313 + 314 + struct atmel_hlcdc_plane_state; 315 + 316 + /** 317 + * struct atmel_lcdc_dc_ops - describes atmel_lcdc ops group 318 + * to differentiate HLCDC and XLCDC IP code support 319 + * @plane_setup_scaler: update the vertical and horizontal scaling factors 320 + * @update_lcdc_buffers: update the each LCDC layers DMA registers 321 + * @lcdc_atomic_disable: disable LCDC interrupts and layers 322 + * @lcdc_update_general_settings: update each LCDC layers general 323 + * configuration register 324 + * @lcdc_atomic_update: enable the LCDC layers and interrupts 325 + * @lcdc_csc_init: update the color space conversion co-efficient of 326 + * High-end overlay register 327 + * @lcdc_irq_dbg: to raise alert incase of interrupt overrun in any LCDC layer 328 + */ 329 + struct atmel_lcdc_dc_ops { 330 + void (*plane_setup_scaler)(struct atmel_hlcdc_plane *plane, 331 + struct atmel_hlcdc_plane_state *state); 332 + void (*lcdc_update_buffers)(struct atmel_hlcdc_plane *plane, 333 + struct atmel_hlcdc_plane_state *state, 334 + u32 sr, int i); 335 + void (*lcdc_atomic_disable)(struct atmel_hlcdc_plane *plane); 336 + void (*lcdc_update_general_settings)(struct atmel_hlcdc_plane *plane, 337 + struct atmel_hlcdc_plane_state *state); 338 + void (*lcdc_atomic_update)(struct atmel_hlcdc_plane *plane, 339 + struct atmel_hlcdc_dc *dc); 340 + void (*lcdc_csc_init)(struct atmel_hlcdc_plane *plane, 341 + const struct atmel_hlcdc_layer_desc *desc); 342 + void (*lcdc_irq_dbg)(struct atmel_hlcdc_plane *plane, 343 + const struct atmel_hlcdc_layer_desc *desc); 344 + }; 345 + 346 + extern const struct atmel_lcdc_dc_ops atmel_hlcdc_ops; 347 + 348 + /** 292 349 * Atmel HLCDC Display Controller description structure. 293 350 * 294 351 * This structure describes the HLCDC IP capabilities and depends on the ··· 363 306 * @fixed_clksrc: true if clock source is fixed 364 307 * @layers: a layer description table describing available layers 365 308 * @nlayers: layer description table size 309 + * @ops: atmel lcdc dc ops 366 310 */ 367 311 struct atmel_hlcdc_dc_desc { 368 312 int min_width; ··· 377 319 bool fixed_clksrc; 378 320 const struct atmel_hlcdc_layer_desc *layers; 379 321 int nlayers; 380 - }; 381 - 382 - /** 383 - * Atmel HLCDC Display Controller. 384 - * 385 - * @desc: HLCDC Display Controller description 386 - * @dscrpool: DMA coherent pool used to allocate DMA descriptors 387 - * @hlcdc: pointer to the atmel_hlcdc structure provided by the MFD device 388 - * @fbdev: framebuffer device attached to the Display Controller 389 - * @crtc: CRTC provided by the display controller 390 - * @planes: instantiated planes 391 - * @layers: active HLCDC layers 392 - * @suspend: used to store the HLCDC state when entering suspend 393 - */ 394 - struct atmel_hlcdc_dc { 395 - const struct atmel_hlcdc_dc_desc *desc; 396 - struct dma_pool *dscrpool; 397 - struct atmel_hlcdc *hlcdc; 398 - struct drm_crtc *crtc; 399 - struct atmel_hlcdc_layer *layers[ATMEL_HLCDC_MAX_LAYERS]; 400 - struct { 401 - u32 imr; 402 - struct drm_atomic_state *state; 403 - } suspend; 322 + const struct atmel_lcdc_dc_ops *ops; 404 323 }; 405 324 406 325 extern struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_formats;
+119 -70
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
··· 282 282 coeff_tab[i]); 283 283 } 284 284 285 - static void atmel_hlcdc_plane_setup_scaler(struct atmel_hlcdc_plane *plane, 286 - struct atmel_hlcdc_plane_state *state) 285 + static 286 + void atmel_hlcdc_plane_setup_scaler(struct atmel_hlcdc_plane *plane, 287 + struct atmel_hlcdc_plane_state *state) 287 288 { 288 289 const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; 289 290 u32 xfactor, yfactor; ··· 336 335 struct atmel_hlcdc_plane_state *state) 337 336 { 338 337 const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; 338 + struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private; 339 339 340 340 if (desc->layout.size) 341 341 atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.size, ··· 354 352 ATMEL_HLCDC_LAYER_POS(state->crtc_x, 355 353 state->crtc_y)); 356 354 357 - atmel_hlcdc_plane_setup_scaler(plane, state); 355 + dc->desc->ops->plane_setup_scaler(plane, state); 358 356 } 359 357 360 - static void 361 - atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane, 362 - struct atmel_hlcdc_plane_state *state) 358 + static 359 + void atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane, 360 + struct atmel_hlcdc_plane_state *state) 363 361 { 364 362 unsigned int cfg = ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16 | state->ahb_id; 365 363 const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; ··· 439 437 } 440 438 } 441 439 440 + static void atmel_hlcdc_update_buffers(struct atmel_hlcdc_plane *plane, 441 + struct atmel_hlcdc_plane_state *state, 442 + u32 sr, int i) 443 + { 444 + atmel_hlcdc_layer_write_reg(&plane->layer, 445 + ATMEL_HLCDC_LAYER_PLANE_HEAD(i), 446 + state->dscrs[i]->self); 447 + 448 + if (sr & ATMEL_HLCDC_LAYER_EN) 449 + return; 450 + 451 + atmel_hlcdc_layer_write_reg(&plane->layer, 452 + ATMEL_HLCDC_LAYER_PLANE_ADDR(i), 453 + state->dscrs[i]->addr); 454 + atmel_hlcdc_layer_write_reg(&plane->layer, 455 + ATMEL_HLCDC_LAYER_PLANE_CTRL(i), 456 + state->dscrs[i]->ctrl); 457 + atmel_hlcdc_layer_write_reg(&plane->layer, 458 + ATMEL_HLCDC_LAYER_PLANE_NEXT(i), 459 + state->dscrs[i]->self); 460 + } 461 + 442 462 static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane, 443 - struct atmel_hlcdc_plane_state *state) 463 + struct atmel_hlcdc_plane_state *state) 444 464 { 445 465 const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; 466 + struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private; 446 467 struct drm_framebuffer *fb = state->base.fb; 447 468 u32 sr; 448 469 int i; ··· 477 452 478 453 state->dscrs[i]->addr = gem->dma_addr + state->offsets[i]; 479 454 480 - atmel_hlcdc_layer_write_reg(&plane->layer, 481 - ATMEL_HLCDC_LAYER_PLANE_HEAD(i), 482 - state->dscrs[i]->self); 483 - 484 - if (!(sr & ATMEL_HLCDC_LAYER_EN)) { 485 - atmel_hlcdc_layer_write_reg(&plane->layer, 486 - ATMEL_HLCDC_LAYER_PLANE_ADDR(i), 487 - state->dscrs[i]->addr); 488 - atmel_hlcdc_layer_write_reg(&plane->layer, 489 - ATMEL_HLCDC_LAYER_PLANE_CTRL(i), 490 - state->dscrs[i]->ctrl); 491 - atmel_hlcdc_layer_write_reg(&plane->layer, 492 - ATMEL_HLCDC_LAYER_PLANE_NEXT(i), 493 - state->dscrs[i]->self); 494 - } 455 + dc->desc->ops->lcdc_update_buffers(plane, state, sr, i); 495 456 496 457 if (desc->layout.xstride[i]) 497 458 atmel_hlcdc_layer_write_cfg(&plane->layer, ··· 723 712 return 0; 724 713 } 725 714 726 - static void atmel_hlcdc_plane_atomic_disable(struct drm_plane *p, 727 - struct drm_atomic_state *state) 715 + static void atmel_hlcdc_atomic_disable(struct atmel_hlcdc_plane *plane) 728 716 { 729 - struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p); 730 - 731 717 /* Disable interrupts */ 732 718 atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_IDR, 733 719 0xffffffff); ··· 739 731 atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_ISR); 740 732 } 741 733 742 - static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p, 743 - struct drm_atomic_state *state) 734 + static void atmel_hlcdc_plane_atomic_disable(struct drm_plane *p, 735 + struct drm_atomic_state *state) 744 736 { 745 - struct drm_plane_state *new_s = drm_atomic_get_new_plane_state(state, 746 - p); 747 737 struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p); 748 - struct atmel_hlcdc_plane_state *hstate = 749 - drm_plane_state_to_atmel_hlcdc_plane_state(new_s); 738 + struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private; 739 + 740 + dc->desc->ops->lcdc_atomic_disable(plane); 741 + } 742 + 743 + static void atmel_hlcdc_atomic_update(struct atmel_hlcdc_plane *plane, 744 + struct atmel_hlcdc_dc *dc) 745 + { 750 746 u32 sr; 751 - 752 - if (!new_s->crtc || !new_s->fb) 753 - return; 754 - 755 - if (!hstate->base.visible) { 756 - atmel_hlcdc_plane_atomic_disable(p, state); 757 - return; 758 - } 759 - 760 - atmel_hlcdc_plane_update_pos_and_size(plane, hstate); 761 - atmel_hlcdc_plane_update_general_settings(plane, hstate); 762 - atmel_hlcdc_plane_update_format(plane, hstate); 763 - atmel_hlcdc_plane_update_clut(plane, hstate); 764 - atmel_hlcdc_plane_update_buffers(plane, hstate); 765 - atmel_hlcdc_plane_update_disc_area(plane, hstate); 766 747 767 748 /* Enable the overrun interrupts. */ 768 749 atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_IER, ··· 762 765 /* Apply the new config at the next SOF event. */ 763 766 sr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHSR); 764 767 atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHER, 765 - ATMEL_HLCDC_LAYER_UPDATE | 766 - (sr & ATMEL_HLCDC_LAYER_EN ? 767 - ATMEL_HLCDC_LAYER_A2Q : ATMEL_HLCDC_LAYER_EN)); 768 + ATMEL_HLCDC_LAYER_UPDATE | 769 + (sr & ATMEL_HLCDC_LAYER_EN ? 770 + ATMEL_HLCDC_LAYER_A2Q : ATMEL_HLCDC_LAYER_EN)); 771 + } 772 + 773 + static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p, 774 + struct drm_atomic_state *state) 775 + { 776 + struct drm_plane_state *new_s = drm_atomic_get_new_plane_state(state, 777 + p); 778 + struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p); 779 + struct atmel_hlcdc_plane_state *hstate = 780 + drm_plane_state_to_atmel_hlcdc_plane_state(new_s); 781 + struct atmel_hlcdc_dc *dc = p->dev->dev_private; 782 + 783 + if (!new_s->crtc || !new_s->fb) 784 + return; 785 + 786 + if (!hstate->base.visible) { 787 + atmel_hlcdc_plane_atomic_disable(p, state); 788 + return; 789 + } 790 + 791 + atmel_hlcdc_plane_update_pos_and_size(plane, hstate); 792 + dc->desc->ops->lcdc_update_general_settings(plane, hstate); 793 + atmel_hlcdc_plane_update_format(plane, hstate); 794 + atmel_hlcdc_plane_update_clut(plane, hstate); 795 + atmel_hlcdc_plane_update_buffers(plane, hstate); 796 + atmel_hlcdc_plane_update_disc_area(plane, hstate); 797 + 798 + dc->desc->ops->lcdc_atomic_update(plane, dc); 799 + } 800 + 801 + static void atmel_hlcdc_csc_init(struct atmel_hlcdc_plane *plane, 802 + const struct atmel_hlcdc_layer_desc *desc) 803 + { 804 + /* 805 + * TODO: declare a "yuv-to-rgb-conv-factors" property to let 806 + * userspace modify these factors (using a BLOB property ?). 807 + */ 808 + static const u32 hlcdc_csc_coeffs[] = { 809 + 0x4c900091, 810 + 0x7a5f5090, 811 + 0x40040890 812 + }; 813 + 814 + for (int i = 0; i < ARRAY_SIZE(hlcdc_csc_coeffs); i++) { 815 + atmel_hlcdc_layer_write_cfg(&plane->layer, 816 + desc->layout.csc + i, 817 + hlcdc_csc_coeffs[i]); 818 + } 768 819 } 769 820 770 821 static int atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane) 771 822 { 772 823 const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; 824 + struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private; 773 825 774 826 if (desc->type == ATMEL_HLCDC_OVERLAY_LAYER || 775 827 desc->type == ATMEL_HLCDC_CURSOR_LAYER) { ··· 842 796 return ret; 843 797 } 844 798 845 - if (desc->layout.csc) { 846 - /* 847 - * TODO: decare a "yuv-to-rgb-conv-factors" property to let 848 - * userspace modify these factors (using a BLOB property ?). 849 - */ 850 - atmel_hlcdc_layer_write_cfg(&plane->layer, 851 - desc->layout.csc, 852 - 0x4c900091); 853 - atmel_hlcdc_layer_write_cfg(&plane->layer, 854 - desc->layout.csc + 1, 855 - 0x7a5f5090); 856 - atmel_hlcdc_layer_write_cfg(&plane->layer, 857 - desc->layout.csc + 2, 858 - 0x40040890); 859 - } 799 + if (desc->layout.csc) 800 + dc->desc->ops->lcdc_csc_init(plane, desc); 860 801 861 802 return 0; 862 803 } 863 804 864 - void atmel_hlcdc_plane_irq(struct atmel_hlcdc_plane *plane) 805 + static void atmel_hlcdc_irq_dbg(struct atmel_hlcdc_plane *plane, 806 + const struct atmel_hlcdc_layer_desc *desc) 865 807 { 866 - const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; 867 - u32 isr; 868 - 869 - isr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_ISR); 808 + u32 isr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_ISR); 870 809 871 810 /* 872 811 * There's not much we can do in case of overrun except informing ··· 864 833 dev_dbg(plane->base.dev->dev, "overrun on plane %s\n", 865 834 desc->name); 866 835 } 836 + 837 + void atmel_hlcdc_plane_irq(struct atmel_hlcdc_plane *plane) 838 + { 839 + const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; 840 + struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private; 841 + 842 + dc->desc->ops->lcdc_irq_dbg(plane, desc); 843 + } 844 + 845 + const struct atmel_lcdc_dc_ops atmel_hlcdc_ops = { 846 + .plane_setup_scaler = atmel_hlcdc_plane_setup_scaler, 847 + .lcdc_update_buffers = atmel_hlcdc_update_buffers, 848 + .lcdc_atomic_disable = atmel_hlcdc_atomic_disable, 849 + .lcdc_update_general_settings = atmel_hlcdc_plane_update_general_settings, 850 + .lcdc_atomic_update = atmel_hlcdc_atomic_update, 851 + .lcdc_csc_init = atmel_hlcdc_csc_init, 852 + .lcdc_irq_dbg = atmel_hlcdc_irq_dbg, 853 + }; 867 854 868 855 static const struct drm_plane_helper_funcs atmel_hlcdc_layer_plane_helper_funcs = { 869 856 .atomic_check = atmel_hlcdc_plane_atomic_check,