brintos

brintos / linux-shallow public Read only

0
0
Text · 17.5 KiB · abb8b11 Raw
781 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * OMAP1 internal LCD controller4 *5 * Copyright (C) 2004 Nokia Corporation6 * Author: Imre Deak <imre.deak@nokia.com>7 */8#include <linux/module.h>9#include <linux/device.h>10#include <linux/interrupt.h>11#include <linux/spinlock.h>12#include <linux/err.h>13#include <linux/mm.h>14#include <linux/fb.h>15#include <linux/dma-mapping.h>16#include <linux/vmalloc.h>17#include <linux/clk.h>18#include <linux/gfp.h>19 20#include <linux/soc/ti/omap1-io.h>21#include <linux/soc/ti/omap1-soc.h>22#include <linux/omap-dma.h>23 24#include <asm/mach-types.h>25 26#include "omapfb.h"27 28#include "lcdc.h"29#include "lcd_dma.h"30 31#define MODULE_NAME			"lcdc"32 33#define MAX_PALETTE_SIZE		PAGE_SIZE34 35enum lcdc_load_mode {36	OMAP_LCDC_LOAD_PALETTE,37	OMAP_LCDC_LOAD_FRAME,38	OMAP_LCDC_LOAD_PALETTE_AND_FRAME39};40 41static struct omap_lcd_controller {42	enum omapfb_update_mode	update_mode;43	int			ext_mode;44 45	unsigned long		frame_offset;46	int			screen_width;47	int			xres;48	int			yres;49 50	enum omapfb_color_format	color_mode;51	int			bpp;52	void			*palette_virt;53	dma_addr_t		palette_phys;54	int			palette_code;55	int			palette_size;56 57	unsigned int		irq_mask;58	struct completion	last_frame_complete;59	struct completion	palette_load_complete;60	struct clk		*lcd_ck;61	struct omapfb_device	*fbdev;62 63	void			(*dma_callback)(void *data);64	void			*dma_callback_data;65 66	dma_addr_t		vram_phys;67	void			*vram_virt;68	unsigned long		vram_size;69} lcdc;70 71static inline void enable_irqs(int mask)72{73	lcdc.irq_mask |= mask;74}75 76static inline void disable_irqs(int mask)77{78	lcdc.irq_mask &= ~mask;79}80 81static void set_load_mode(enum lcdc_load_mode mode)82{83	u32 l;84 85	l = omap_readl(OMAP_LCDC_CONTROL);86	l &= ~(3 << 20);87	switch (mode) {88	case OMAP_LCDC_LOAD_PALETTE:89		l |= 1 << 20;90		break;91	case OMAP_LCDC_LOAD_FRAME:92		l |= 2 << 20;93		break;94	case OMAP_LCDC_LOAD_PALETTE_AND_FRAME:95		break;96	default:97		BUG();98	}99	omap_writel(l, OMAP_LCDC_CONTROL);100}101 102static void enable_controller(void)103{104	u32 l;105 106	l = omap_readl(OMAP_LCDC_CONTROL);107	l |= OMAP_LCDC_CTRL_LCD_EN;108	l &= ~OMAP_LCDC_IRQ_MASK;109	l |= lcdc.irq_mask | OMAP_LCDC_IRQ_DONE;	/* enabled IRQs */110	omap_writel(l, OMAP_LCDC_CONTROL);111}112 113static void disable_controller_async(void)114{115	u32 l;116	u32 mask;117 118	l = omap_readl(OMAP_LCDC_CONTROL);119	mask = OMAP_LCDC_CTRL_LCD_EN | OMAP_LCDC_IRQ_MASK;120	/*121	 * Preserve the DONE mask, since we still want to get the122	 * final DONE irq. It will be disabled in the IRQ handler.123	 */124	mask &= ~OMAP_LCDC_IRQ_DONE;125	l &= ~mask;126	omap_writel(l, OMAP_LCDC_CONTROL);127}128 129static void disable_controller(void)130{131	init_completion(&lcdc.last_frame_complete);132	disable_controller_async();133	if (!wait_for_completion_timeout(&lcdc.last_frame_complete,134				msecs_to_jiffies(500)))135		dev_err(lcdc.fbdev->dev, "timeout waiting for FRAME DONE\n");136}137 138static void reset_controller(u32 status)139{140	static unsigned long reset_count;141	static unsigned long last_jiffies;142 143	disable_controller_async();144	reset_count++;145	if (reset_count == 1 || time_after(jiffies, last_jiffies + HZ)) {146		dev_err(lcdc.fbdev->dev,147			  "resetting (status %#010x,reset count %lu)\n",148			  status, reset_count);149		last_jiffies = jiffies;150	}151	if (reset_count < 100) {152		enable_controller();153	} else {154		reset_count = 0;155		dev_err(lcdc.fbdev->dev,156			"too many reset attempts, giving up.\n");157	}158}159 160/*161 * Configure the LCD DMA according to the current mode specified by parameters162 * in lcdc.fbdev and fbdev->var.163 */164static void setup_lcd_dma(void)165{166	static const int dma_elem_type[] = {167		0,168		OMAP_DMA_DATA_TYPE_S8,169		OMAP_DMA_DATA_TYPE_S16,170		0,171		OMAP_DMA_DATA_TYPE_S32,172	};173	struct omapfb_plane_struct *plane = lcdc.fbdev->fb_info[0]->par;174	struct fb_var_screeninfo *var = &lcdc.fbdev->fb_info[0]->var;175	unsigned long	src;176	int		esize, xelem, yelem;177 178	src = lcdc.vram_phys + lcdc.frame_offset;179 180	switch (var->rotate) {181	case 0:182		if (plane->info.mirror || (src & 3) ||183		    lcdc.color_mode == OMAPFB_COLOR_YUV420 ||184		    (lcdc.xres & 1))185			esize = 2;186		else187			esize = 4;188		xelem = lcdc.xres * lcdc.bpp / 8 / esize;189		yelem = lcdc.yres;190		break;191	case 90:192	case 180:193	case 270:194		if (cpu_is_omap15xx()) {195			BUG();196		}197		esize = 2;198		xelem = lcdc.yres * lcdc.bpp / 16;199		yelem = lcdc.xres;200		break;201	default:202		BUG();203		return;204	}205#ifdef VERBOSE206	dev_dbg(lcdc.fbdev->dev,207		 "setup_dma: src %#010lx esize %d xelem %d yelem %d\n",208		 src, esize, xelem, yelem);209#endif210	omap_set_lcd_dma_b1(src, xelem, yelem, dma_elem_type[esize]);211	if (!cpu_is_omap15xx()) {212		int bpp = lcdc.bpp;213 214		/*215		 * YUV support is only for external mode when we have the216		 * YUV window embedded in a 16bpp frame buffer.217		 */218		if (lcdc.color_mode == OMAPFB_COLOR_YUV420)219			bpp = 16;220		/* Set virtual xres elem size */221		omap_set_lcd_dma_b1_vxres(222			lcdc.screen_width * bpp / 8 / esize);223		/* Setup transformations */224		omap_set_lcd_dma_b1_rotation(var->rotate);225		omap_set_lcd_dma_b1_mirror(plane->info.mirror);226	}227	omap_setup_lcd_dma();228}229 230static irqreturn_t lcdc_irq_handler(int irq, void *dev_id)231{232	u32 status;233 234	status = omap_readl(OMAP_LCDC_STATUS);235 236	if (status & (OMAP_LCDC_STAT_FUF | OMAP_LCDC_STAT_SYNC_LOST))237		reset_controller(status);238	else {239		if (status & OMAP_LCDC_STAT_DONE) {240			u32 l;241 242			/*243			 * Disable IRQ_DONE. The status bit will be cleared244			 * only when the controller is reenabled and we don't245			 * want to get more interrupts.246			 */247			l = omap_readl(OMAP_LCDC_CONTROL);248			l &= ~OMAP_LCDC_IRQ_DONE;249			omap_writel(l, OMAP_LCDC_CONTROL);250			complete(&lcdc.last_frame_complete);251		}252		if (status & OMAP_LCDC_STAT_LOADED_PALETTE) {253			disable_controller_async();254			complete(&lcdc.palette_load_complete);255		}256	}257 258	/*259	 * Clear these interrupt status bits.260	 * Sync_lost, FUF bits were cleared by disabling the LCD controller261	 * LOADED_PALETTE can be cleared this way only in palette only262	 * load mode. In other load modes it's cleared by disabling the263	 * controller.264	 */265	status &= ~(OMAP_LCDC_STAT_VSYNC |266		    OMAP_LCDC_STAT_LOADED_PALETTE |267		    OMAP_LCDC_STAT_ABC |268		    OMAP_LCDC_STAT_LINE_INT);269	omap_writel(status, OMAP_LCDC_STATUS);270	return IRQ_HANDLED;271}272 273/*274 * Change to a new video mode. We defer this to a later time to avoid any275 * flicker and not to mess up the current LCD DMA context. For this we disable276 * the LCD controller, which will generate a DONE irq after the last frame has277 * been transferred. Then it'll be safe to reconfigure both the LCD controller278 * as well as the LCD DMA.279 */280static int omap_lcdc_setup_plane(int plane, int channel_out,281				 unsigned long offset, int screen_width,282				 int pos_x, int pos_y, int width, int height,283				 int color_mode)284{285	struct fb_var_screeninfo *var = &lcdc.fbdev->fb_info[0]->var;286	struct lcd_panel *panel = lcdc.fbdev->panel;287	int rot_x, rot_y;288 289	if (var->rotate == 0) {290		rot_x = panel->x_res;291		rot_y = panel->y_res;292	} else {293		rot_x = panel->y_res;294		rot_y = panel->x_res;295	}296	if (plane != 0 || channel_out != 0 || pos_x != 0 || pos_y != 0 ||297	    width > rot_x || height > rot_y) {298#ifdef VERBOSE299		dev_dbg(lcdc.fbdev->dev,300			"invalid plane params plane %d pos_x %d pos_y %d "301			"w %d h %d\n", plane, pos_x, pos_y, width, height);302#endif303		return -EINVAL;304	}305 306	lcdc.frame_offset = offset;307	lcdc.xres = width;308	lcdc.yres = height;309	lcdc.screen_width = screen_width;310	lcdc.color_mode = color_mode;311 312	switch (color_mode) {313	case OMAPFB_COLOR_CLUT_8BPP:314		lcdc.bpp = 8;315		lcdc.palette_code = 0x3000;316		lcdc.palette_size = 512;317		break;318	case OMAPFB_COLOR_RGB565:319		lcdc.bpp = 16;320		lcdc.palette_code = 0x4000;321		lcdc.palette_size = 32;322		break;323	case OMAPFB_COLOR_RGB444:324		lcdc.bpp = 16;325		lcdc.palette_code = 0x4000;326		lcdc.palette_size = 32;327		break;328	case OMAPFB_COLOR_YUV420:329		if (lcdc.ext_mode) {330			lcdc.bpp = 12;331			break;332		}333		fallthrough;334	case OMAPFB_COLOR_YUV422:335		if (lcdc.ext_mode) {336			lcdc.bpp = 16;337			break;338		}339		fallthrough;340	default:341		/* FIXME: other BPPs.342		 * bpp1: code  0,     size 256343		 * bpp2: code  0x1000 size 256344		 * bpp4: code  0x2000 size 256345		 * bpp12: code 0x4000 size 32346		 */347		dev_dbg(lcdc.fbdev->dev, "invalid color mode %d\n", color_mode);348		BUG();349		return -1;350	}351 352	if (lcdc.ext_mode) {353		setup_lcd_dma();354		return 0;355	}356 357	if (lcdc.update_mode == OMAPFB_AUTO_UPDATE) {358		disable_controller();359		omap_stop_lcd_dma();360		setup_lcd_dma();361		enable_controller();362	}363 364	return 0;365}366 367static int omap_lcdc_enable_plane(int plane, int enable)368{369	dev_dbg(lcdc.fbdev->dev,370		"plane %d enable %d update_mode %d ext_mode %d\n",371		plane, enable, lcdc.update_mode, lcdc.ext_mode);372	if (plane != OMAPFB_PLANE_GFX)373		return -EINVAL;374 375	return 0;376}377 378/*379 * Configure the LCD DMA for a palette load operation and do the palette380 * downloading synchronously. We don't use the frame+palette load mode of381 * the controller, since the palette can always be downloaded separately.382 */383static void load_palette(void)384{385	u16	*palette;386 387	palette = (u16 *)lcdc.palette_virt;388 389	*(u16 *)palette &= 0x0fff;390	*(u16 *)palette |= lcdc.palette_code;391 392	omap_set_lcd_dma_b1(lcdc.palette_phys,393		lcdc.palette_size / 4 + 1, 1, OMAP_DMA_DATA_TYPE_S32);394 395	omap_set_lcd_dma_single_transfer(1);396	omap_setup_lcd_dma();397 398	init_completion(&lcdc.palette_load_complete);399	enable_irqs(OMAP_LCDC_IRQ_LOADED_PALETTE);400	set_load_mode(OMAP_LCDC_LOAD_PALETTE);401	enable_controller();402	if (!wait_for_completion_timeout(&lcdc.palette_load_complete,403				msecs_to_jiffies(500)))404		dev_err(lcdc.fbdev->dev, "timeout waiting for FRAME DONE\n");405	/* The controller gets disabled in the irq handler */406	disable_irqs(OMAP_LCDC_IRQ_LOADED_PALETTE);407	omap_stop_lcd_dma();408 409	omap_set_lcd_dma_single_transfer(lcdc.ext_mode);410}411 412/* Used only in internal controller mode */413static int omap_lcdc_setcolreg(u_int regno, u16 red, u16 green, u16 blue,414			       u16 transp, int update_hw_pal)415{416	u16 *palette;417 418	if (lcdc.color_mode != OMAPFB_COLOR_CLUT_8BPP || regno > 255)419		return -EINVAL;420 421	palette = (u16 *)lcdc.palette_virt;422 423	palette[regno] &= ~0x0fff;424	palette[regno] |= ((red >> 12) << 8) | ((green >> 12) << 4 ) |425			   (blue >> 12);426 427	if (update_hw_pal) {428		disable_controller();429		omap_stop_lcd_dma();430		load_palette();431		setup_lcd_dma();432		set_load_mode(OMAP_LCDC_LOAD_FRAME);433		enable_controller();434	}435 436	return 0;437}438 439static void calc_ck_div(int is_tft, int pck, int *pck_div)440{441	unsigned long lck;442 443	pck = max(1, pck);444	lck = clk_get_rate(lcdc.lcd_ck);445	*pck_div = (lck + pck - 1) / pck;446	if (is_tft)447		*pck_div = max(2, *pck_div);448	else449		*pck_div = max(3, *pck_div);450	if (*pck_div > 255) {451		/* FIXME: try to adjust logic clock divider as well */452		*pck_div = 255;453		dev_warn(lcdc.fbdev->dev, "pixclock %d kHz too low.\n",454			 pck / 1000);455	}456}457 458static inline void setup_regs(void)459{460	u32 l;461	struct lcd_panel *panel = lcdc.fbdev->panel;462	int is_tft = panel->config & OMAP_LCDC_PANEL_TFT;463	unsigned long lck;464	int pcd;465 466	l = omap_readl(OMAP_LCDC_CONTROL);467	l &= ~OMAP_LCDC_CTRL_LCD_TFT;468	l |= is_tft ? OMAP_LCDC_CTRL_LCD_TFT : 0;469#ifdef CONFIG_MACH_OMAP_PALMTE470/* FIXME:if (machine_is_omap_palmte()) { */471		/* PalmTE uses alternate TFT setting in 8BPP mode */472		l |= (is_tft && panel->bpp == 8) ? 0x810000 : 0;473/*	} */474#endif475	omap_writel(l, OMAP_LCDC_CONTROL);476 477	l = omap_readl(OMAP_LCDC_TIMING2);478	l &= ~(((1 << 6) - 1) << 20);479	l |= (panel->config & OMAP_LCDC_SIGNAL_MASK) << 20;480	omap_writel(l, OMAP_LCDC_TIMING2);481 482	l = panel->x_res - 1;483	l |= (panel->hsw - 1) << 10;484	l |= (panel->hfp - 1) << 16;485	l |= (panel->hbp - 1) << 24;486	omap_writel(l, OMAP_LCDC_TIMING0);487 488	l = panel->y_res - 1;489	l |= (panel->vsw - 1) << 10;490	l |= panel->vfp << 16;491	l |= panel->vbp << 24;492	omap_writel(l, OMAP_LCDC_TIMING1);493 494	l = omap_readl(OMAP_LCDC_TIMING2);495	l &= ~0xff;496 497	lck = clk_get_rate(lcdc.lcd_ck);498 499	if (!panel->pcd)500		calc_ck_div(is_tft, panel->pixel_clock * 1000, &pcd);501	else {502		dev_warn(lcdc.fbdev->dev,503		    "Pixel clock divider value is obsolete.\n"504		    "Try to set pixel_clock to %lu and pcd to 0 "505		    "in drivers/video/omap/lcd_%s.c and submit a patch.\n",506			lck / panel->pcd / 1000, panel->name);507 508		pcd = panel->pcd;509	}510	l |= pcd & 0xff;511	l |= panel->acb << 8;512	omap_writel(l, OMAP_LCDC_TIMING2);513 514	/* update panel info with the exact clock */515	panel->pixel_clock = lck / pcd / 1000;516}517 518/*519 * Configure the LCD controller, download the color palette and start a looped520 * DMA transfer of the frame image data. Called only in internal521 * controller mode.522 */523static int omap_lcdc_set_update_mode(enum omapfb_update_mode mode)524{525	int r = 0;526 527	if (mode != lcdc.update_mode) {528		switch (mode) {529		case OMAPFB_AUTO_UPDATE:530			setup_regs();531			load_palette();532 533			/* Setup and start LCD DMA */534			setup_lcd_dma();535 536			set_load_mode(OMAP_LCDC_LOAD_FRAME);537			enable_irqs(OMAP_LCDC_IRQ_DONE);538			/* This will start the actual DMA transfer */539			enable_controller();540			lcdc.update_mode = mode;541			break;542		case OMAPFB_UPDATE_DISABLED:543			disable_controller();544			omap_stop_lcd_dma();545			lcdc.update_mode = mode;546			break;547		default:548			r = -EINVAL;549		}550	}551 552	return r;553}554 555static enum omapfb_update_mode omap_lcdc_get_update_mode(void)556{557	return lcdc.update_mode;558}559 560/* PM code called only in internal controller mode */561static void omap_lcdc_suspend(void)562{563	omap_lcdc_set_update_mode(OMAPFB_UPDATE_DISABLED);564}565 566static void omap_lcdc_resume(void)567{568	omap_lcdc_set_update_mode(OMAPFB_AUTO_UPDATE);569}570 571static void omap_lcdc_get_caps(int plane, struct omapfb_caps *caps)572{573	return;574}575 576int omap_lcdc_set_dma_callback(void (*callback)(void *data), void *data)577{578	BUG_ON(callback == NULL);579 580	if (lcdc.dma_callback)581		return -EBUSY;582	else {583		lcdc.dma_callback = callback;584		lcdc.dma_callback_data = data;585	}586	return 0;587}588EXPORT_SYMBOL(omap_lcdc_set_dma_callback);589 590void omap_lcdc_free_dma_callback(void)591{592	lcdc.dma_callback = NULL;593}594EXPORT_SYMBOL(omap_lcdc_free_dma_callback);595 596static void lcdc_dma_handler(u16 status, void *data)597{598	if (lcdc.dma_callback)599		lcdc.dma_callback(lcdc.dma_callback_data);600}601 602static int alloc_palette_ram(void)603{604	lcdc.palette_virt = dma_alloc_wc(lcdc.fbdev->dev, MAX_PALETTE_SIZE,605					 &lcdc.palette_phys, GFP_KERNEL);606	if (lcdc.palette_virt == NULL) {607		dev_err(lcdc.fbdev->dev, "failed to alloc palette memory\n");608		return -ENOMEM;609	}610	memset(lcdc.palette_virt, 0, MAX_PALETTE_SIZE);611 612	return 0;613}614 615static void free_palette_ram(void)616{617	dma_free_wc(lcdc.fbdev->dev, MAX_PALETTE_SIZE, lcdc.palette_virt,618		    lcdc.palette_phys);619}620 621static int alloc_fbmem(struct omapfb_mem_region *region)622{623	int bpp;624	int frame_size;625	struct lcd_panel *panel = lcdc.fbdev->panel;626 627	bpp = panel->bpp;628	if (bpp == 12)629		bpp = 16;630	frame_size = PAGE_ALIGN(panel->x_res * bpp / 8 * panel->y_res);631	if (region->size > frame_size)632		frame_size = region->size;633	lcdc.vram_size = frame_size;634	lcdc.vram_virt = dma_alloc_wc(lcdc.fbdev->dev, lcdc.vram_size,635				      &lcdc.vram_phys, GFP_KERNEL);636	if (lcdc.vram_virt == NULL) {637		dev_err(lcdc.fbdev->dev, "unable to allocate FB DMA memory\n");638		return -ENOMEM;639	}640	region->size = frame_size;641	region->paddr = lcdc.vram_phys;642	region->vaddr = lcdc.vram_virt;643	region->alloc = 1;644 645	memset(lcdc.vram_virt, 0, lcdc.vram_size);646 647	return 0;648}649 650static void free_fbmem(void)651{652	dma_free_wc(lcdc.fbdev->dev, lcdc.vram_size, lcdc.vram_virt,653		    lcdc.vram_phys);654}655 656static int setup_fbmem(struct omapfb_mem_desc *req_md)657{658	if (!req_md->region_cnt) {659		dev_err(lcdc.fbdev->dev, "no memory regions defined\n");660		return -EINVAL;661	}662 663	if (req_md->region_cnt > 1) {664		dev_err(lcdc.fbdev->dev, "only one plane is supported\n");665		req_md->region_cnt = 1;666	}667 668	return alloc_fbmem(&req_md->region[0]);669}670 671static int omap_lcdc_init(struct omapfb_device *fbdev, int ext_mode,672			  struct omapfb_mem_desc *req_vram)673{674	int r;675	u32 l;676	int rate;677	struct clk *tc_ck;678 679	lcdc.irq_mask = 0;680 681	lcdc.fbdev = fbdev;682	lcdc.ext_mode = ext_mode;683 684	l = 0;685	omap_writel(l, OMAP_LCDC_CONTROL);686 687	/* FIXME:688	 * According to errata some platforms have a clock rate limitiation689	 */690	lcdc.lcd_ck = clk_get(fbdev->dev, "lcd_ck");691	if (IS_ERR(lcdc.lcd_ck)) {692		dev_err(fbdev->dev, "unable to access LCD clock\n");693		r = PTR_ERR(lcdc.lcd_ck);694		goto fail0;695	}696 697	tc_ck = clk_get(fbdev->dev, "tc_ck");698	if (IS_ERR(tc_ck)) {699		dev_err(fbdev->dev, "unable to access TC clock\n");700		r = PTR_ERR(tc_ck);701		goto fail1;702	}703 704	rate = clk_get_rate(tc_ck);705	clk_put(tc_ck);706 707	if (machine_is_ams_delta())708		rate /= 4;709	r = clk_set_rate(lcdc.lcd_ck, rate);710	if (r) {711		dev_err(fbdev->dev, "failed to adjust LCD rate\n");712		goto fail1;713	}714	clk_prepare_enable(lcdc.lcd_ck);715 716	r = request_irq(fbdev->int_irq, lcdc_irq_handler, 0, MODULE_NAME, fbdev);717	if (r) {718		dev_err(fbdev->dev, "unable to get IRQ\n");719		goto fail2;720	}721 722	r = omap_request_lcd_dma(lcdc_dma_handler, NULL);723	if (r) {724		dev_err(fbdev->dev, "unable to get LCD DMA\n");725		goto fail3;726	}727 728	omap_set_lcd_dma_single_transfer(ext_mode);729	omap_set_lcd_dma_ext_controller(ext_mode);730 731	if (!ext_mode)732		if ((r = alloc_palette_ram()) < 0)733			goto fail4;734 735	if ((r = setup_fbmem(req_vram)) < 0)736		goto fail5;737 738	pr_info("omapfb: LCDC initialized\n");739 740	return 0;741fail5:742	if (!ext_mode)743		free_palette_ram();744fail4:745	omap_free_lcd_dma();746fail3:747	free_irq(fbdev->int_irq, lcdc.fbdev);748fail2:749	clk_disable_unprepare(lcdc.lcd_ck);750fail1:751	clk_put(lcdc.lcd_ck);752fail0:753	return r;754}755 756static void omap_lcdc_cleanup(void)757{758	if (!lcdc.ext_mode)759		free_palette_ram();760	free_fbmem();761	omap_free_lcd_dma();762	free_irq(lcdc.fbdev->int_irq, lcdc.fbdev);763	clk_disable_unprepare(lcdc.lcd_ck);764	clk_put(lcdc.lcd_ck);765}766 767const struct lcd_ctrl omap1_int_ctrl = {768	.name			= "internal",769	.init			= omap_lcdc_init,770	.cleanup		= omap_lcdc_cleanup,771	.get_caps		= omap_lcdc_get_caps,772	.set_update_mode	= omap_lcdc_set_update_mode,773	.get_update_mode	= omap_lcdc_get_update_mode,774	.update_window		= NULL,775	.suspend		= omap_lcdc_suspend,776	.resume			= omap_lcdc_resume,777	.setup_plane		= omap_lcdc_setup_plane,778	.enable_plane		= omap_lcdc_enable_plane,779	.setcolreg		= omap_lcdc_setcolreg,780};781