drivers/gpu/drm/kmb/kmb_drv.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/kmb/kmb_drv.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/kmb/kmb_drv.c
Extension
.c
Size
16921 bytes
Lines
638
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (kmb->plane_status[plane_id].disable) {
				kmb_clr_bitmask_lcd(kmb,
						    LCD_LAYERn_DMA_CFG
						    (plane_id),
						    LCD_DMA_LAYER_ENABLE);

				kmb_clr_bitmask_lcd(kmb, LCD_CONTROL,
						    kmb->plane_status[plane_id].ctrl);

				ctrl = kmb_read_lcd(kmb, LCD_CONTROL);
				if (!(ctrl & (LCD_CTRL_VL1_ENABLE |
				    LCD_CTRL_VL2_ENABLE |
				    LCD_CTRL_GL1_ENABLE |
				    LCD_CTRL_GL2_ENABLE))) {
					/* If no LCD layers are using DMA,
					 * then disable DMA pipelined AXI read
					 * transactions.
					 */
					kmb_clr_bitmask_lcd(kmb, LCD_CONTROL,
							    LCD_CTRL_PIPELINE_DMA);
				}

				kmb->plane_status[plane_id].disable = false;
			}
		}
		if (kmb->kmb_under_flow) {
			/* DMA Recovery after underflow */
			dma0_state = (kmb->layer_no == 0) ?
			    LCD_VIDEO0_DMA0_STATE : LCD_VIDEO1_DMA0_STATE;
			dma1_state = (kmb->layer_no == 0) ?
			    LCD_VIDEO0_DMA1_STATE : LCD_VIDEO1_DMA1_STATE;

			do {
				kmb_write_lcd(kmb, LCD_FIFO_FLUSH, 1);
				val = kmb_read_lcd(kmb, dma0_state)
				    & LCD_DMA_STATE_ACTIVE;
				val1 = kmb_read_lcd(kmb, dma1_state)
				    & LCD_DMA_STATE_ACTIVE;
			} while ((val || val1));
			/* disable dma */
			kmb_clr_bitmask_lcd(kmb,
					    LCD_LAYERn_DMA_CFG(kmb->layer_no),
					    LCD_DMA_LAYER_ENABLE);
			kmb_write_lcd(kmb, LCD_FIFO_FLUSH, 1);
			kmb->kmb_flush_done = 1;
			kmb->kmb_under_flow = 0;
		}
	}

	if (status & LCD_INT_LINE_CMP) {
		/* clear line compare interrupt */
		kmb_write_lcd(kmb, LCD_INT_CLEAR, LCD_INT_LINE_CMP);
	}

	if (status & LCD_INT_VERT_COMP) {
		/* Read VSTATUS */
		val = kmb_read_lcd(kmb, LCD_VSTATUS);
		val = (val & LCD_VSTATUS_VERTICAL_STATUS_MASK);
		switch (val) {
		case LCD_VSTATUS_COMPARE_VSYNC:
			/* Clear vertical compare interrupt */
			kmb_write_lcd(kmb, LCD_INT_CLEAR, LCD_INT_VERT_COMP);
			if (kmb->kmb_flush_done) {
				kmb_set_bitmask_lcd(kmb,
						    LCD_LAYERn_DMA_CFG
						    (kmb->layer_no),
						    LCD_DMA_LAYER_ENABLE);
				kmb->kmb_flush_done = 0;
			}
			drm_crtc_handle_vblank(&kmb->crtc);
			break;
		case LCD_VSTATUS_COMPARE_BACKPORCH:
		case LCD_VSTATUS_COMPARE_ACTIVE:
		case LCD_VSTATUS_COMPARE_FRONT_PORCH:
			kmb_write_lcd(kmb, LCD_INT_CLEAR, LCD_INT_VERT_COMP);
			break;
		}
	}
	if (status & LCD_INT_DMA_ERR) {
		val =
		    (status & LCD_INT_DMA_ERR &
		     kmb_read_lcd(kmb, LCD_INT_ENABLE));
		/* LAYER0 - VL0 */
		if (val & (LAYER0_DMA_FIFO_UNDERFLOW |
			   LAYER0_DMA_CB_FIFO_UNDERFLOW |
			   LAYER0_DMA_CR_FIFO_UNDERFLOW)) {
			kmb->kmb_under_flow++;
			drm_info(&kmb->drm,
				 "!LAYER0:VL0 DMA UNDERFLOW val = 0x%lx,under_flow=%d",
			     val, kmb->kmb_under_flow);

Annotation

Implementation Notes