summaryrefslogtreecommitdiff
path: root/drivers/video/mxs/lcdif.c
blob: f7d48a6fb3e9ef4e097a70701b8cdbaa1fbc6843 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
 * Freescale MXS LCDIF low-level routines
 *
 * Author: Vitaly Wool <vital@embeddedalley.com>
 *
 * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
 * Copyright (C) 2009-2010 Freescale Semiconductor, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <linux/delay.h>
#include <linux/dma-mapping.h>

#include <mach/hardware.h>
#include <mach/lcdif.h>
#include <mach/regs-lcdif.h>
#include <mach/system.h>

#define REGS_LCDIF_BASE IO_ADDRESS(LCDIF_PHYS_ADDR)

void mxs_init_lcdif(void)
{
	__raw_writel(BM_LCDIF_CTRL_CLKGATE,
		     REGS_LCDIF_BASE + HW_LCDIF_CTRL_CLR);
	/* Reset controller */
	__raw_writel(BM_LCDIF_CTRL_SFTRST, REGS_LCDIF_BASE + HW_LCDIF_CTRL_SET);
	udelay(10);

	/* Take controller out of reset */
	__raw_writel(BM_LCDIF_CTRL_SFTRST | BM_LCDIF_CTRL_CLKGATE,
		     REGS_LCDIF_BASE + HW_LCDIF_CTRL_CLR);

	/* Setup the bus protocol */
	__raw_writel(BM_LCDIF_CTRL1_MODE86,
		     REGS_LCDIF_BASE + HW_LCDIF_CTRL1_CLR);
	__raw_writel(BM_LCDIF_CTRL1_BUSY_ENABLE,
		     REGS_LCDIF_BASE + HW_LCDIF_CTRL1_CLR);

	/* Take display out of reset */
	__raw_writel(BM_LCDIF_CTRL1_RESET,
		     REGS_LCDIF_BASE + HW_LCDIF_CTRL1_SET);

	/* VSYNC is an input by default */
	__raw_writel(BM_LCDIF_VDCTRL0_VSYNC_OEB,
		     REGS_LCDIF_BASE + HW_LCDIF_VDCTRL0_SET);

	/* Reset display */
	__raw_writel(BM_LCDIF_CTRL1_RESET,
		     REGS_LCDIF_BASE + HW_LCDIF_CTRL1_CLR);
	udelay(10);
	__raw_writel(BM_LCDIF_CTRL1_RESET,
		     REGS_LCDIF_BASE + HW_LCDIF_CTRL1_SET);
	udelay(10);
}
EXPORT_SYMBOL(mxs_init_lcdif);

int mxs_lcdif_dma_init(struct device *dev, dma_addr_t phys, int memsize)
{
	__raw_writel(BM_LCDIF_CTRL_LCDIF_MASTER,
		     REGS_LCDIF_BASE + HW_LCDIF_CTRL_SET);

	__raw_writel(phys, REGS_LCDIF_BASE + HW_LCDIF_CUR_BUF);
	__raw_writel(phys, REGS_LCDIF_BASE + HW_LCDIF_NEXT_BUF);

	return 0;
}
EXPORT_SYMBOL(mxs_lcdif_dma_init);

void mxs_lcdif_dma_release(void)
{
	__raw_writel(BM_LCDIF_CTRL_LCDIF_MASTER,
		     REGS_LCDIF_BASE + HW_LCDIF_CTRL_CLR);
	return;
}
EXPORT_SYMBOL(mxs_lcdif_dma_release);

void mxs_lcdif_run(void)
{
	__raw_writel(BM_LCDIF_CTRL_LCDIF_MASTER,
		     REGS_LCDIF_BASE + HW_LCDIF_CTRL_SET);
	__raw_writel(BM_LCDIF_CTRL_RUN, REGS_LCDIF_BASE + HW_LCDIF_CTRL_SET);
}
EXPORT_SYMBOL(mxs_lcdif_run);

void mxs_lcdif_stop(void)
{
	__raw_writel(BM_LCDIF_CTRL_RUN, REGS_LCDIF_BASE + HW_LCDIF_CTRL_CLR);
	__raw_writel(BM_LCDIF_CTRL_LCDIF_MASTER,
		     REGS_LCDIF_BASE + HW_LCDIF_CTRL_CLR);
	udelay(100);
}
EXPORT_SYMBOL(mxs_lcdif_stop);

int mxs_lcdif_pan_display(dma_addr_t addr)
{
	__raw_writel(addr, REGS_LCDIF_BASE + HW_LCDIF_NEXT_BUF);

	return 0;
}

EXPORT_SYMBOL(mxs_lcdif_pan_display);

static BLOCKING_NOTIFIER_HEAD(lcdif_client_list);

int mxs_lcdif_register_client(struct notifier_block *nb)
{
	return blocking_notifier_chain_register(&lcdif_client_list, nb);
}

EXPORT_SYMBOL(mxs_lcdif_register_client);

void mxs_lcdif_unregister_client(struct notifier_block *nb)
{
	blocking_notifier_chain_unregister(&lcdif_client_list, nb);
}
EXPORT_SYMBOL(mxs_lcdif_unregister_client);

void mxs_lcdif_notify_clients(unsigned long event,
			      struct mxs_platform_fb_entry *pentry)
{
	blocking_notifier_call_chain(&lcdif_client_list, event, pentry);
}
EXPORT_SYMBOL(mxs_lcdif_notify_clients);