aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-nv24.xml121
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt.xml1
-rw-r--r--Documentation/fb/api.txt306
-rw-r--r--MAINTAINERS6
-rw-r--r--arch/arm/mach-omap2/board-4430sdp.c23
-rw-r--r--arch/arm/mach-omap2/board-omap4panda.c25
-rw-r--r--arch/arm/mach-omap2/display.c39
-rw-r--r--arch/arm/mach-shmobile/board-ag5evm.c43
-rw-r--r--arch/arm/mach-shmobile/board-ap4evb.c32
-rw-r--r--arch/arm/mach-shmobile/board-mackerel.c4
-rw-r--r--arch/arm/mach-shmobile/clock-sh7372.c4
-rw-r--r--arch/arm/mach-shmobile/clock-sh73a0.c4
-rw-r--r--arch/sh/boards/mach-ap325rxa/setup.c2
-rw-r--r--arch/sh/boards/mach-ecovec24/setup.c2
-rw-r--r--arch/sh/boards/mach-kfr2r09/setup.c2
-rw-r--r--arch/sh/boards/mach-migor/setup.c4
-rw-r--r--arch/sh/boards/mach-se/7724/setup.c2
-rw-r--r--drivers/media/video/omap/omap_vout.c33
-rw-r--r--drivers/video/Kconfig1
-rw-r--r--drivers/video/Makefile2
-rw-r--r--drivers/video/amifb.c3732
-rw-r--r--drivers/video/atmel_lcdfb.c37
-rw-r--r--drivers/video/cirrusfb.c268
-rw-r--r--drivers/video/controlfb.c2
-rw-r--r--drivers/video/display/Kconfig24
-rw-r--r--drivers/video/display/Makefile6
-rw-r--r--drivers/video/display/display-sysfs.c219
-rw-r--r--drivers/video/fbmem.c14
-rw-r--r--drivers/video/fsl-diu-fb.c587
-rw-r--r--drivers/video/grvga.c4
-rw-r--r--drivers/video/i810/i810_main.c16
-rw-r--r--drivers/video/matrox/matroxfb_base.c1
-rw-r--r--drivers/video/matrox/matroxfb_crtc2.c1
-rw-r--r--drivers/video/mbx/mbxfb.c13
-rw-r--r--drivers/video/mxsfb.c13
-rw-r--r--drivers/video/nuc900fb.c13
-rw-r--r--drivers/video/omap/lcd_ams_delta.c15
-rw-r--r--drivers/video/omap/lcd_h3.c16
-rw-r--r--drivers/video/omap/lcd_htcherald.c16
-rw-r--r--drivers/video/omap/lcd_inn1510.c16
-rw-r--r--drivers/video/omap/lcd_inn1610.c16
-rw-r--r--drivers/video/omap/lcd_mipid.c1
-rw-r--r--drivers/video/omap/lcd_osk.c16
-rw-r--r--drivers/video/omap/lcd_palmte.c16
-rw-r--r--drivers/video/omap/lcd_palmtt.c15
-rw-r--r--drivers/video/omap/lcd_palmz71.c15
-rw-r--r--drivers/video/omap2/displays/Kconfig2
-rw-r--r--drivers/video/omap2/displays/panel-acx565akm.c1
-rw-r--r--drivers/video/omap2/displays/panel-generic-dpi.c66
-rw-r--r--drivers/video/omap2/displays/panel-n8x0.c1
-rw-r--r--drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c62
-rw-r--r--drivers/video/omap2/displays/panel-taal.c38
-rw-r--r--drivers/video/omap2/displays/panel-tpo-td043mtea1.c1
-rw-r--r--drivers/video/omap2/dss/Makefile3
-rw-r--r--drivers/video/omap2/dss/apply.c1324
-rw-r--r--drivers/video/omap2/dss/core.c2
-rw-r--r--drivers/video/omap2/dss/dispc.c407
-rw-r--r--drivers/video/omap2/dss/dispc.h11
-rw-r--r--drivers/video/omap2/dss/dispc_coefs.c326
-rw-r--r--drivers/video/omap2/dss/dpi.c7
-rw-r--r--drivers/video/omap2/dss/dsi.c612
-rw-r--r--drivers/video/omap2/dss/dss.h74
-rw-r--r--drivers/video/omap2/dss/dss_features.c11
-rw-r--r--drivers/video/omap2/dss/dss_features.h1
-rw-r--r--drivers/video/omap2/dss/hdmi.c59
-rw-r--r--drivers/video/omap2/dss/manager.c1221
-rw-r--r--drivers/video/omap2/dss/overlay.c435
-rw-r--r--drivers/video/omap2/dss/rfbi.c1
-rw-r--r--drivers/video/omap2/dss/sdi.c8
-rw-r--r--drivers/video/omap2/dss/ti_hdmi.h10
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c37
-rw-r--r--drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h3
-rw-r--r--drivers/video/omap2/dss/venc.c28
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c42
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c14
-rw-r--r--drivers/video/omap2/omapfb/omapfb-sysfs.c4
-rw-r--r--drivers/video/omap2/omapfb/omapfb.h11
-rw-r--r--drivers/video/pnx4008/pnxrgbfb.c13
-rw-r--r--drivers/video/pnx4008/sdum.c13
-rw-r--r--drivers/video/pxa168fb.c12
-rw-r--r--drivers/video/pxa3xx-gcu.c15
-rw-r--r--drivers/video/s3c-fb.c202
-rw-r--r--drivers/video/s3c2410fb.c29
-rw-r--r--drivers/video/s3fb.c30
-rw-r--r--drivers/video/sbuslib.c2
-rw-r--r--drivers/video/sh7760fb.c13
-rw-r--r--drivers/video/sh_mipi_dsi.c218
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c375
-rw-r--r--drivers/video/sh_mobile_meram.c13
-rw-r--r--drivers/video/sm501fb.c13
-rw-r--r--drivers/video/vt8500lcdfb.c13
-rw-r--r--drivers/video/w100fb.c13
-rw-r--r--drivers/video/wm8505fb.c13
-rw-r--r--drivers/video/wmt_ge_rops.c13
-rw-r--r--drivers/video/xilinxfb.c20
-rw-r--r--include/linux/display.h61
-rw-r--r--include/linux/fb.h14
-rw-r--r--include/linux/videodev2.h2
-rw-r--r--include/linux/zorro_ids.h4
-rw-r--r--include/video/omapdss.h58
-rw-r--r--include/video/sh_mipi_dsi.h21
-rw-r--r--include/video/sh_mobile_lcdc.h4
102 files changed, 6285 insertions, 5469 deletions
diff --git a/Documentation/DocBook/media/v4l/pixfmt-nv24.xml b/Documentation/DocBook/media/v4l/pixfmt-nv24.xml
new file mode 100644
index 000000000000..fb255f2ca9dd
--- /dev/null
+++ b/Documentation/DocBook/media/v4l/pixfmt-nv24.xml
@@ -0,0 +1,121 @@
1 <refentry>
2 <refmeta>
3 <refentrytitle>V4L2_PIX_FMT_NV24 ('NV24'), V4L2_PIX_FMT_NV42 ('NV42')</refentrytitle>
4 &manvol;
5 </refmeta>
6 <refnamediv>
7 <refname id="V4L2-PIX-FMT-NV24"><constant>V4L2_PIX_FMT_NV24</constant></refname>
8 <refname id="V4L2-PIX-FMT-NV42"><constant>V4L2_PIX_FMT_NV42</constant></refname>
9 <refpurpose>Formats with full horizontal and vertical
10chroma resolutions, also known as YUV 4:4:4. One luminance and one
11chrominance plane with alternating chroma samples as opposed to
12<constant>V4L2_PIX_FMT_YVU420</constant></refpurpose>
13 </refnamediv>
14 <refsect1>
15 <title>Description</title>
16
17 <para>These are two-plane versions of the YUV 4:4:4 format. The three
18 components are separated into two sub-images or planes. The Y plane is
19 first, with each Y sample stored in one byte per pixel. For
20 <constant>V4L2_PIX_FMT_NV24</constant>, a combined CbCr plane
21 immediately follows the Y plane in memory. The CbCr plane has the same
22 width and height, in pixels, as the Y plane (and the image). Each line
23 contains one CbCr pair per pixel, with each Cb and Cr sample stored in
24 one byte. <constant>V4L2_PIX_FMT_NV42</constant> is the same except that
25 the Cb and Cr samples are swapped, the CrCb plane starts with a Cr
26 sample.</para>
27
28 <para>If the Y plane has pad bytes after each row, then the CbCr plane
29 has twice as many pad bytes after its rows.</para>
30
31 <example>
32 <title><constant>V4L2_PIX_FMT_NV24</constant> 4 &times; 4
33pixel image</title>
34
35 <formalpara>
36 <title>Byte Order.</title>
37 <para>Each cell is one byte.
38 <informaltable frame="none">
39 <tgroup cols="9" align="center">
40 <colspec align="left" colwidth="2*" />
41 <tbody valign="top">
42 <row>
43 <entry>start&nbsp;+&nbsp;0:</entry>
44 <entry>Y'<subscript>00</subscript></entry>
45 <entry>Y'<subscript>01</subscript></entry>
46 <entry>Y'<subscript>02</subscript></entry>
47 <entry>Y'<subscript>03</subscript></entry>
48 </row>
49 <row>
50 <entry>start&nbsp;+&nbsp;4:</entry>
51 <entry>Y'<subscript>10</subscript></entry>
52 <entry>Y'<subscript>11</subscript></entry>
53 <entry>Y'<subscript>12</subscript></entry>
54 <entry>Y'<subscript>13</subscript></entry>
55 </row>
56 <row>
57 <entry>start&nbsp;+&nbsp;8:</entry>
58 <entry>Y'<subscript>20</subscript></entry>
59 <entry>Y'<subscript>21</subscript></entry>
60 <entry>Y'<subscript>22</subscript></entry>
61 <entry>Y'<subscript>23</subscript></entry>
62 </row>
63 <row>
64 <entry>start&nbsp;+&nbsp;12:</entry>
65 <entry>Y'<subscript>30</subscript></entry>
66 <entry>Y'<subscript>31</subscript></entry>
67 <entry>Y'<subscript>32</subscript></entry>
68 <entry>Y'<subscript>33</subscript></entry>
69 </row>
70 <row>
71 <entry>start&nbsp;+&nbsp;16:</entry>
72 <entry>Cb<subscript>00</subscript></entry>
73 <entry>Cr<subscript>00</subscript></entry>
74 <entry>Cb<subscript>01</subscript></entry>
75 <entry>Cr<subscript>01</subscript></entry>
76 <entry>Cb<subscript>02</subscript></entry>
77 <entry>Cr<subscript>02</subscript></entry>
78 <entry>Cb<subscript>03</subscript></entry>
79 <entry>Cr<subscript>03</subscript></entry>
80 </row>
81 <row>
82 <entry>start&nbsp;+&nbsp;24:</entry>
83 <entry>Cb<subscript>10</subscript></entry>
84 <entry>Cr<subscript>10</subscript></entry>
85 <entry>Cb<subscript>11</subscript></entry>
86 <entry>Cr<subscript>11</subscript></entry>
87 <entry>Cb<subscript>12</subscript></entry>
88 <entry>Cr<subscript>12</subscript></entry>
89 <entry>Cb<subscript>13</subscript></entry>
90 <entry>Cr<subscript>13</subscript></entry>
91 </row>
92 <row>
93 <entry>start&nbsp;+&nbsp;32:</entry>
94 <entry>Cb<subscript>20</subscript></entry>
95 <entry>Cr<subscript>20</subscript></entry>
96 <entry>Cb<subscript>21</subscript></entry>
97 <entry>Cr<subscript>21</subscript></entry>
98 <entry>Cb<subscript>22</subscript></entry>
99 <entry>Cr<subscript>22</subscript></entry>
100 <entry>Cb<subscript>23</subscript></entry>
101 <entry>Cr<subscript>23</subscript></entry>
102 </row>
103 <row>
104 <entry>start&nbsp;+&nbsp;40:</entry>
105 <entry>Cb<subscript>30</subscript></entry>
106 <entry>Cr<subscript>30</subscript></entry>
107 <entry>Cb<subscript>31</subscript></entry>
108 <entry>Cr<subscript>31</subscript></entry>
109 <entry>Cb<subscript>32</subscript></entry>
110 <entry>Cr<subscript>32</subscript></entry>
111 <entry>Cb<subscript>33</subscript></entry>
112 <entry>Cr<subscript>33</subscript></entry>
113 </row>
114 </tbody>
115 </tgroup>
116 </informaltable>
117 </para>
118 </formalpara>
119 </example>
120 </refsect1>
121 </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt.xml b/Documentation/DocBook/media/v4l/pixfmt.xml
index 2ff6b7776d7f..aef4615fb07b 100644
--- a/Documentation/DocBook/media/v4l/pixfmt.xml
+++ b/Documentation/DocBook/media/v4l/pixfmt.xml
@@ -714,6 +714,7 @@ information.</para>
714 &sub-nv12m; 714 &sub-nv12m;
715 &sub-nv12mt; 715 &sub-nv12mt;
716 &sub-nv16; 716 &sub-nv16;
717 &sub-nv24;
717 &sub-m420; 718 &sub-m420;
718 </section> 719 </section>
719 720
diff --git a/Documentation/fb/api.txt b/Documentation/fb/api.txt
new file mode 100644
index 000000000000..d4ff7de85700
--- /dev/null
+++ b/Documentation/fb/api.txt
@@ -0,0 +1,306 @@
1 The Frame Buffer Device API
2 ---------------------------
3
4Last revised: June 21, 2011
5
6
70. Introduction
8---------------
9
10This document describes the frame buffer API used by applications to interact
11with frame buffer devices. In-kernel APIs between device drivers and the frame
12buffer core are not described.
13
14Due to a lack of documentation in the original frame buffer API, drivers
15behaviours differ in subtle (and not so subtle) ways. This document describes
16the recommended API implementation, but applications should be prepared to
17deal with different behaviours.
18
19
201. Capabilities
21---------------
22
23Device and driver capabilities are reported in the fixed screen information
24capabilities field.
25
26struct fb_fix_screeninfo {
27 ...
28 __u16 capabilities; /* see FB_CAP_* */
29 ...
30};
31
32Application should use those capabilities to find out what features they can
33expect from the device and driver.
34
35- FB_CAP_FOURCC
36
37The driver supports the four character code (FOURCC) based format setting API.
38When supported, formats are configured using a FOURCC instead of manually
39specifying color components layout.
40
41
422. Types and visuals
43--------------------
44
45Pixels are stored in memory in hardware-dependent formats. Applications need
46to be aware of the pixel storage format in order to write image data to the
47frame buffer memory in the format expected by the hardware.
48
49Formats are described by frame buffer types and visuals. Some visuals require
50additional information, which are stored in the variable screen information
51bits_per_pixel, grayscale, red, green, blue and transp fields.
52
53Visuals describe how color information is encoded and assembled to create
54macropixels. Types describe how macropixels are stored in memory. The following
55types and visuals are supported.
56
57- FB_TYPE_PACKED_PIXELS
58
59Macropixels are stored contiguously in a single plane. If the number of bits
60per macropixel is not a multiple of 8, whether macropixels are padded to the
61next multiple of 8 bits or packed together into bytes depends on the visual.
62
63Padding at end of lines may be present and is then reported through the fixed
64screen information line_length field.
65
66- FB_TYPE_PLANES
67
68Macropixels are split across multiple planes. The number of planes is equal to
69the number of bits per macropixel, with plane i'th storing i'th bit from all
70macropixels.
71
72Planes are located contiguously in memory.
73
74- FB_TYPE_INTERLEAVED_PLANES
75
76Macropixels are split across multiple planes. The number of planes is equal to
77the number of bits per macropixel, with plane i'th storing i'th bit from all
78macropixels.
79
80Planes are interleaved in memory. The interleave factor, defined as the
81distance in bytes between the beginning of two consecutive interleaved blocks
82belonging to different planes, is stored in the fixed screen information
83type_aux field.
84
85- FB_TYPE_FOURCC
86
87Macropixels are stored in memory as described by the format FOURCC identifier
88stored in the variable screen information grayscale field.
89
90- FB_VISUAL_MONO01
91
92Pixels are black or white and stored on a number of bits (typically one)
93specified by the variable screen information bpp field.
94
95Black pixels are represented by all bits set to 1 and white pixels by all bits
96set to 0. When the number of bits per pixel is smaller than 8, several pixels
97are packed together in a byte.
98
99FB_VISUAL_MONO01 is currently used with FB_TYPE_PACKED_PIXELS only.
100
101- FB_VISUAL_MONO10
102
103Pixels are black or white and stored on a number of bits (typically one)
104specified by the variable screen information bpp field.
105
106Black pixels are represented by all bits set to 0 and white pixels by all bits
107set to 1. When the number of bits per pixel is smaller than 8, several pixels
108are packed together in a byte.
109
110FB_VISUAL_MONO01 is currently used with FB_TYPE_PACKED_PIXELS only.
111
112- FB_VISUAL_TRUECOLOR
113
114Pixels are broken into red, green and blue components, and each component
115indexes a read-only lookup table for the corresponding value. Lookup tables
116are device-dependent, and provide linear or non-linear ramps.
117
118Each component is stored in a macropixel according to the variable screen
119information red, green, blue and transp fields.
120
121- FB_VISUAL_PSEUDOCOLOR and FB_VISUAL_STATIC_PSEUDOCOLOR
122
123Pixel values are encoded as indices into a colormap that stores red, green and
124blue components. The colormap is read-only for FB_VISUAL_STATIC_PSEUDOCOLOR
125and read-write for FB_VISUAL_PSEUDOCOLOR.
126
127Each pixel value is stored in the number of bits reported by the variable
128screen information bits_per_pixel field.
129
130- FB_VISUAL_DIRECTCOLOR
131
132Pixels are broken into red, green and blue components, and each component
133indexes a programmable lookup table for the corresponding value.
134
135Each component is stored in a macropixel according to the variable screen
136information red, green, blue and transp fields.
137
138- FB_VISUAL_FOURCC
139
140Pixels are encoded and interpreted as described by the format FOURCC
141identifier stored in the variable screen information grayscale field.
142
143
1443. Screen information
145---------------------
146
147Screen information are queried by applications using the FBIOGET_FSCREENINFO
148and FBIOGET_VSCREENINFO ioctls. Those ioctls take a pointer to a
149fb_fix_screeninfo and fb_var_screeninfo structure respectively.
150
151struct fb_fix_screeninfo stores device independent unchangeable information
152about the frame buffer device and the current format. Those information can't
153be directly modified by applications, but can be changed by the driver when an
154application modifies the format.
155
156struct fb_fix_screeninfo {
157 char id[16]; /* identification string eg "TT Builtin" */
158 unsigned long smem_start; /* Start of frame buffer mem */
159 /* (physical address) */
160 __u32 smem_len; /* Length of frame buffer mem */
161 __u32 type; /* see FB_TYPE_* */
162 __u32 type_aux; /* Interleave for interleaved Planes */
163 __u32 visual; /* see FB_VISUAL_* */
164 __u16 xpanstep; /* zero if no hardware panning */
165 __u16 ypanstep; /* zero if no hardware panning */
166 __u16 ywrapstep; /* zero if no hardware ywrap */
167 __u32 line_length; /* length of a line in bytes */
168 unsigned long mmio_start; /* Start of Memory Mapped I/O */
169 /* (physical address) */
170 __u32 mmio_len; /* Length of Memory Mapped I/O */
171 __u32 accel; /* Indicate to driver which */
172 /* specific chip/card we have */
173 __u16 capabilities; /* see FB_CAP_* */
174 __u16 reserved[2]; /* Reserved for future compatibility */
175};
176
177struct fb_var_screeninfo stores device independent changeable information
178about a frame buffer device, its current format and video mode, as well as
179other miscellaneous parameters.
180
181struct fb_var_screeninfo {
182 __u32 xres; /* visible resolution */
183 __u32 yres;
184 __u32 xres_virtual; /* virtual resolution */
185 __u32 yres_virtual;
186 __u32 xoffset; /* offset from virtual to visible */
187 __u32 yoffset; /* resolution */
188
189 __u32 bits_per_pixel; /* guess what */
190 __u32 grayscale; /* 0 = color, 1 = grayscale, */
191 /* >1 = FOURCC */
192 struct fb_bitfield red; /* bitfield in fb mem if true color, */
193 struct fb_bitfield green; /* else only length is significant */
194 struct fb_bitfield blue;
195 struct fb_bitfield transp; /* transparency */
196
197 __u32 nonstd; /* != 0 Non standard pixel format */
198
199 __u32 activate; /* see FB_ACTIVATE_* */
200
201 __u32 height; /* height of picture in mm */
202 __u32 width; /* width of picture in mm */
203
204 __u32 accel_flags; /* (OBSOLETE) see fb_info.flags */
205
206 /* Timing: All values in pixclocks, except pixclock (of course) */
207 __u32 pixclock; /* pixel clock in ps (pico seconds) */
208 __u32 left_margin; /* time from sync to picture */
209 __u32 right_margin; /* time from picture to sync */
210 __u32 upper_margin; /* time from sync to picture */
211 __u32 lower_margin;
212 __u32 hsync_len; /* length of horizontal sync */
213 __u32 vsync_len; /* length of vertical sync */
214 __u32 sync; /* see FB_SYNC_* */
215 __u32 vmode; /* see FB_VMODE_* */
216 __u32 rotate; /* angle we rotate counter clockwise */
217 __u32 colorspace; /* colorspace for FOURCC-based modes */
218 __u32 reserved[4]; /* Reserved for future compatibility */
219};
220
221To modify variable information, applications call the FBIOPUT_VSCREENINFO
222ioctl with a pointer to a fb_var_screeninfo structure. If the call is
223successful, the driver will update the fixed screen information accordingly.
224
225Instead of filling the complete fb_var_screeninfo structure manually,
226applications should call the FBIOGET_VSCREENINFO ioctl and modify only the
227fields they care about.
228
229
2304. Format configuration
231-----------------------
232
233Frame buffer devices offer two ways to configure the frame buffer format: the
234legacy API and the FOURCC-based API.
235
236
237The legacy API has been the only frame buffer format configuration API for a
238long time and is thus widely used by application. It is the recommended API
239for applications when using RGB and grayscale formats, as well as legacy
240non-standard formats.
241
242To select a format, applications set the fb_var_screeninfo bits_per_pixel field
243to the desired frame buffer depth. Values up to 8 will usually map to
244monochrome, grayscale or pseudocolor visuals, although this is not required.
245
246- For grayscale formats, applications set the grayscale field to one. The red,
247 blue, green and transp fields must be set to 0 by applications and ignored by
248 drivers. Drivers must fill the red, blue and green offsets to 0 and lengths
249 to the bits_per_pixel value.
250
251- For pseudocolor formats, applications set the grayscale field to zero. The
252 red, blue, green and transp fields must be set to 0 by applications and
253 ignored by drivers. Drivers must fill the red, blue and green offsets to 0
254 and lengths to the bits_per_pixel value.
255
256- For truecolor and directcolor formats, applications set the grayscale field
257 to zero, and the red, blue, green and transp fields to describe the layout of
258 color components in memory.
259
260struct fb_bitfield {
261 __u32 offset; /* beginning of bitfield */
262 __u32 length; /* length of bitfield */
263 __u32 msb_right; /* != 0 : Most significant bit is */
264 /* right */
265};
266
267 Pixel values are bits_per_pixel wide and are split in non-overlapping red,
268 green, blue and alpha (transparency) components. Location and size of each
269 component in the pixel value are described by the fb_bitfield offset and
270 length fields. Offset are computed from the right.
271
272 Pixels are always stored in an integer number of bytes. If the number of
273 bits per pixel is not a multiple of 8, pixel values are padded to the next
274 multiple of 8 bits.
275
276Upon successful format configuration, drivers update the fb_fix_screeninfo
277type, visual and line_length fields depending on the selected format.
278
279
280The FOURCC-based API replaces format descriptions by four character codes
281(FOURCC). FOURCCs are abstract identifiers that uniquely define a format
282without explicitly describing it. This is the only API that supports YUV
283formats. Drivers are also encouraged to implement the FOURCC-based API for RGB
284and grayscale formats.
285
286Drivers that support the FOURCC-based API report this capability by setting
287the FB_CAP_FOURCC bit in the fb_fix_screeninfo capabilities field.
288
289FOURCC definitions are located in the linux/videodev2.h header. However, and
290despite starting with the V4L2_PIX_FMT_prefix, they are not restricted to V4L2
291and don't require usage of the V4L2 subsystem. FOURCC documentation is
292available in Documentation/DocBook/v4l/pixfmt.xml.
293
294To select a format, applications set the grayscale field to the desired FOURCC.
295For YUV formats, they should also select the appropriate colorspace by setting
296the colorspace field to one of the colorspaces listed in linux/videodev2.h and
297documented in Documentation/DocBook/v4l/colorspaces.xml.
298
299The red, green, blue and transp fields are not used with the FOURCC-based API.
300For forward compatibility reasons applications must zero those fields, and
301drivers must ignore them. Values other than 0 may get a meaning in future
302extensions.
303
304Upon successful format configuration, drivers update the fb_fix_screeninfo
305type, visual and line_length fields depending on the selected format. The type
306and visual fields are set to FB_TYPE_FOURCC and FB_VISUAL_FOURCC respectively.
diff --git a/MAINTAINERS b/MAINTAINERS
index 4d1ba2022a95..ebbee877330f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5669,6 +5669,12 @@ L: alsa-devel@alsa-project.org (moderated for non-subscribers)
5669S: Supported 5669S: Supported
5670F: sound/soc/samsung 5670F: sound/soc/samsung
5671 5671
5672SAMSUNG FRAMEBUFFER DRIVER
5673M: Jingoo Han <jg1.han@samsung.com>
5674L: linux-fbdev@vger.kernel.org
5675S: Maintained
5676F: drivers/video/s3c-fb.c
5677
5672SERIAL DRIVERS 5678SERIAL DRIVERS
5673M: Alan Cox <alan@linux.intel.com> 5679M: Alan Cox <alan@linux.intel.com>
5674L: linux-serial@vger.kernel.org 5680L: linux-serial@vger.kernel.org
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 2ceb75d21eb2..39fba9df17fb 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -602,20 +602,6 @@ static void __init omap_sfh7741prox_init(void)
602 __func__, OMAP4_SFH7741_ENABLE_GPIO, error); 602 __func__, OMAP4_SFH7741_ENABLE_GPIO, error);
603} 603}
604 604
605static void sdp4430_hdmi_mux_init(void)
606{
607 /* PAD0_HDMI_HPD_PAD1_HDMI_CEC */
608 omap_mux_init_signal("hdmi_hpd",
609 OMAP_PIN_INPUT_PULLUP);
610 omap_mux_init_signal("hdmi_cec",
611 OMAP_PIN_INPUT_PULLUP);
612 /* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */
613 omap_mux_init_signal("hdmi_ddc_scl",
614 OMAP_PIN_INPUT_PULLUP);
615 omap_mux_init_signal("hdmi_ddc_sda",
616 OMAP_PIN_INPUT_PULLUP);
617}
618
619static struct gpio sdp4430_hdmi_gpios[] = { 605static struct gpio sdp4430_hdmi_gpios[] = {
620 { HDMI_GPIO_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_hpd" }, 606 { HDMI_GPIO_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_hpd" },
621 { HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" }, 607 { HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" },
@@ -833,9 +819,16 @@ static void omap_4430sdp_display_init(void)
833 pr_err("%s: Could not get display_sel GPIO\n", __func__); 819 pr_err("%s: Could not get display_sel GPIO\n", __func__);
834 820
835 sdp4430_lcd_init(); 821 sdp4430_lcd_init();
836 sdp4430_hdmi_mux_init();
837 sdp4430_picodlp_init(); 822 sdp4430_picodlp_init();
838 omap_display_init(&sdp4430_dss_data); 823 omap_display_init(&sdp4430_dss_data);
824 /*
825 * OMAP4460SDP/Blaze and OMAP4430 ES2.3 SDP/Blaze boards and
826 * later have external pull up on the HDMI I2C lines
827 */
828 if (cpu_is_omap446x() || omap_rev() > OMAP4430_REV_ES2_2)
829 omap_hdmi_init(OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP);
830 else
831 omap_hdmi_init(0);
839} 832}
840 833
841#ifdef CONFIG_OMAP_MUX 834#ifdef CONFIG_OMAP_MUX
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index e96a2e7ad36f..30ad40db2cf3 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -412,21 +412,6 @@ int __init omap4_panda_dvi_init(void)
412 return r; 412 return r;
413} 413}
414 414
415
416static void omap4_panda_hdmi_mux_init(void)
417{
418 /* PAD0_HDMI_HPD_PAD1_HDMI_CEC */
419 omap_mux_init_signal("hdmi_hpd",
420 OMAP_PIN_INPUT_PULLUP);
421 omap_mux_init_signal("hdmi_cec",
422 OMAP_PIN_INPUT_PULLUP);
423 /* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */
424 omap_mux_init_signal("hdmi_ddc_scl",
425 OMAP_PIN_INPUT_PULLUP);
426 omap_mux_init_signal("hdmi_ddc_sda",
427 OMAP_PIN_INPUT_PULLUP);
428}
429
430static struct gpio panda_hdmi_gpios[] = { 415static struct gpio panda_hdmi_gpios[] = {
431 { HDMI_GPIO_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_hpd" }, 416 { HDMI_GPIO_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_hpd" },
432 { HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" }, 417 { HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" },
@@ -478,8 +463,16 @@ void omap4_panda_display_init(void)
478 if (r) 463 if (r)
479 pr_err("error initializing panda DVI\n"); 464 pr_err("error initializing panda DVI\n");
480 465
481 omap4_panda_hdmi_mux_init();
482 omap_display_init(&omap4_panda_dss_data); 466 omap_display_init(&omap4_panda_dss_data);
467
468 /*
469 * OMAP4460SDP/Blaze and OMAP4430 ES2.3 SDP/Blaze boards and
470 * later have external pull up on the HDMI I2C lines
471 */
472 if (cpu_is_omap446x() || omap_rev() > OMAP4430_REV_ES2_2)
473 omap_hdmi_init(OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP);
474 else
475 omap_hdmi_init(0);
483} 476}
484 477
485static void __init omap4_panda_init(void) 478static void __init omap4_panda_init(void)
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index bc6cf863a563..3c446d1a1781 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -30,6 +30,7 @@
30#include <plat/omap-pm.h> 30#include <plat/omap-pm.h>
31#include "common.h" 31#include "common.h"
32 32
33#include "mux.h"
33#include "control.h" 34#include "control.h"
34#include "display.h" 35#include "display.h"
35 36
@@ -97,6 +98,36 @@ static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initdata = {
97 { "dss_hdmi", "omapdss_hdmi", -1 }, 98 { "dss_hdmi", "omapdss_hdmi", -1 },
98}; 99};
99 100
101static void omap4_hdmi_mux_pads(enum omap_hdmi_flags flags)
102{
103 u32 reg;
104 u16 control_i2c_1;
105
106 /* PAD0_HDMI_HPD_PAD1_HDMI_CEC */
107 omap_mux_init_signal("hdmi_hpd",
108 OMAP_PIN_INPUT_PULLUP);
109 omap_mux_init_signal("hdmi_cec",
110 OMAP_PIN_INPUT_PULLUP);
111 /* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */
112 omap_mux_init_signal("hdmi_ddc_scl",
113 OMAP_PIN_INPUT_PULLUP);
114 omap_mux_init_signal("hdmi_ddc_sda",
115 OMAP_PIN_INPUT_PULLUP);
116
117 /*
118 * CONTROL_I2C_1: HDMI_DDC_SDA_PULLUPRESX (bit 28) and
119 * HDMI_DDC_SCL_PULLUPRESX (bit 24) are set to disable
120 * internal pull up resistor.
121 */
122 if (flags & OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP) {
123 control_i2c_1 = OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_1;
124 reg = omap4_ctrl_pad_readl(control_i2c_1);
125 reg |= (OMAP4_HDMI_DDC_SDA_PULLUPRESX_MASK |
126 OMAP4_HDMI_DDC_SCL_PULLUPRESX_MASK);
127 omap4_ctrl_pad_writel(reg, control_i2c_1);
128 }
129}
130
100static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes) 131static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
101{ 132{
102 u32 enable_mask, enable_shift; 133 u32 enable_mask, enable_shift;
@@ -130,6 +161,14 @@ static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
130 return 0; 161 return 0;
131} 162}
132 163
164int omap_hdmi_init(enum omap_hdmi_flags flags)
165{
166 if (cpu_is_omap44xx())
167 omap4_hdmi_mux_pads(flags);
168
169 return 0;
170}
171
133static int omap_dsi_enable_pads(int dsi_id, unsigned lane_mask) 172static int omap_dsi_enable_pads(int dsi_id, unsigned lane_mask)
134{ 173{
135 if (cpu_is_omap44xx()) 174 if (cpu_is_omap44xx())
diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c
index a4e6ca04e319..eff8a96c75ee 100644
--- a/arch/arm/mach-shmobile/board-ag5evm.c
+++ b/arch/arm/mach-shmobile/board-ag5evm.c
@@ -271,7 +271,7 @@ static struct sh_mobile_lcdc_info lcdc0_info = {
271 .flags = LCDC_FLAGS_DWPOL, 271 .flags = LCDC_FLAGS_DWPOL,
272 .lcd_size_cfg.width = 44, 272 .lcd_size_cfg.width = 44,
273 .lcd_size_cfg.height = 79, 273 .lcd_size_cfg.height = 79,
274 .bpp = 16, 274 .fourcc = V4L2_PIX_FMT_RGB565,
275 .lcd_cfg = lcdc0_modes, 275 .lcd_cfg = lcdc0_modes,
276 .num_cfg = ARRAY_SIZE(lcdc0_modes), 276 .num_cfg = ARRAY_SIZE(lcdc0_modes),
277 .board_cfg = { 277 .board_cfg = {
@@ -321,12 +321,46 @@ static struct resource mipidsi0_resources[] = {
321 }, 321 },
322}; 322};
323 323
324#define DSI0PHYCR 0xe615006c
325static int sh_mipi_set_dot_clock(struct platform_device *pdev,
326 void __iomem *base,
327 int enable)
328{
329 struct clk *pck;
330 int ret;
331
332 pck = clk_get(&pdev->dev, "dsip_clk");
333 if (IS_ERR(pck)) {
334 ret = PTR_ERR(pck);
335 goto sh_mipi_set_dot_clock_pck_err;
336 }
337
338 if (enable) {
339 clk_set_rate(pck, clk_round_rate(pck, 24000000));
340 __raw_writel(0x2a809010, DSI0PHYCR);
341 clk_enable(pck);
342 } else {
343 clk_disable(pck);
344 }
345
346 ret = 0;
347
348 clk_put(pck);
349
350sh_mipi_set_dot_clock_pck_err:
351 return ret;
352}
353
324static struct sh_mipi_dsi_info mipidsi0_info = { 354static struct sh_mipi_dsi_info mipidsi0_info = {
325 .data_format = MIPI_RGB888, 355 .data_format = MIPI_RGB888,
326 .lcd_chan = &lcdc0_info.ch[0], 356 .lcd_chan = &lcdc0_info.ch[0],
357 .lane = 2,
327 .vsynw_offset = 20, 358 .vsynw_offset = 20,
328 .clksrc = 1, 359 .clksrc = 1,
329 .flags = SH_MIPI_DSI_HSABM, 360 .flags = SH_MIPI_DSI_HSABM |
361 SH_MIPI_DSI_SYNC_PULSES_MODE |
362 SH_MIPI_DSI_HSbyteCLK,
363 .set_dot_clock = sh_mipi_set_dot_clock,
330}; 364};
331 365
332static struct platform_device mipidsi0_device = { 366static struct platform_device mipidsi0_device = {
@@ -472,8 +506,6 @@ static void __init ag5evm_map_io(void)
472 shmobile_setup_console(); 506 shmobile_setup_console();
473} 507}
474 508
475#define DSI0PHYCR 0xe615006c
476
477static void __init ag5evm_init(void) 509static void __init ag5evm_init(void)
478{ 510{
479 sh73a0_pinmux_init(); 511 sh73a0_pinmux_init();
@@ -554,9 +586,6 @@ static void __init ag5evm_init(void)
554 gpio_direction_output(GPIO_PORT235, 0); 586 gpio_direction_output(GPIO_PORT235, 0);
555 lcd_backlight_reset(); 587 lcd_backlight_reset();
556 588
557 /* MIPI-DSI clock setup */
558 __raw_writel(0x2a809010, DSI0PHYCR);
559
560 /* enable SDHI0 on CN15 [SD I/F] */ 589 /* enable SDHI0 on CN15 [SD I/F] */
561 gpio_request(GPIO_FN_SDHICD0, NULL); 590 gpio_request(GPIO_FN_SDHICD0, NULL);
562 gpio_request(GPIO_FN_SDHIWP0, NULL); 591 gpio_request(GPIO_FN_SDHIWP0, NULL);
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index d2e7b73aa9b6..aab0a349f759 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -491,7 +491,7 @@ static struct sh_mobile_lcdc_info lcdc_info = {
491 .meram_dev = &meram_info, 491 .meram_dev = &meram_info,
492 .ch[0] = { 492 .ch[0] = {
493 .chan = LCDC_CHAN_MAINLCD, 493 .chan = LCDC_CHAN_MAINLCD,
494 .bpp = 16, 494 .fourcc = V4L2_PIX_FMT_RGB565,
495 .lcd_cfg = ap4evb_lcdc_modes, 495 .lcd_cfg = ap4evb_lcdc_modes,
496 .num_cfg = ARRAY_SIZE(ap4evb_lcdc_modes), 496 .num_cfg = ARRAY_SIZE(ap4evb_lcdc_modes),
497 .meram_cfg = &lcd_meram_cfg, 497 .meram_cfg = &lcd_meram_cfg,
@@ -564,6 +564,30 @@ static struct platform_device keysc_device = {
564}; 564};
565 565
566/* MIPI-DSI */ 566/* MIPI-DSI */
567#define PHYCTRL 0x0070
568static int sh_mipi_set_dot_clock(struct platform_device *pdev,
569 void __iomem *base,
570 int enable)
571{
572 struct clk *pck = clk_get(&pdev->dev, "dsip_clk");
573 void __iomem *phy = base + PHYCTRL;
574
575 if (IS_ERR(pck))
576 return PTR_ERR(pck);
577
578 if (enable) {
579 clk_set_rate(pck, clk_round_rate(pck, 24000000));
580 iowrite32(ioread32(phy) | (0xb << 8), phy);
581 clk_enable(pck);
582 } else {
583 clk_disable(pck);
584 }
585
586 clk_put(pck);
587
588 return 0;
589}
590
567static struct resource mipidsi0_resources[] = { 591static struct resource mipidsi0_resources[] = {
568 [0] = { 592 [0] = {
569 .start = 0xffc60000, 593 .start = 0xffc60000,
@@ -580,7 +604,11 @@ static struct resource mipidsi0_resources[] = {
580static struct sh_mipi_dsi_info mipidsi0_info = { 604static struct sh_mipi_dsi_info mipidsi0_info = {
581 .data_format = MIPI_RGB888, 605 .data_format = MIPI_RGB888,
582 .lcd_chan = &lcdc_info.ch[0], 606 .lcd_chan = &lcdc_info.ch[0],
607 .lane = 2,
583 .vsynw_offset = 17, 608 .vsynw_offset = 17,
609 .flags = SH_MIPI_DSI_SYNC_PULSES_MODE |
610 SH_MIPI_DSI_HSbyteCLK,
611 .set_dot_clock = sh_mipi_set_dot_clock,
584}; 612};
585 613
586static struct platform_device mipidsi0_device = { 614static struct platform_device mipidsi0_device = {
@@ -798,7 +826,7 @@ static struct sh_mobile_lcdc_info sh_mobile_lcdc1_info = {
798 .meram_dev = &meram_info, 826 .meram_dev = &meram_info,
799 .ch[0] = { 827 .ch[0] = {
800 .chan = LCDC_CHAN_MAINLCD, 828 .chan = LCDC_CHAN_MAINLCD,
801 .bpp = 16, 829 .fourcc = V4L2_PIX_FMT_RGB565,
802 .interface_type = RGB24, 830 .interface_type = RGB24,
803 .clock_divider = 1, 831 .clock_divider = 1,
804 .flags = LCDC_FLAGS_DWPOL, 832 .flags = LCDC_FLAGS_DWPOL,
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index cbc5934ae03f..9b42fbd10f8e 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -388,7 +388,7 @@ static struct sh_mobile_lcdc_info lcdc_info = {
388 .clock_source = LCDC_CLK_BUS, 388 .clock_source = LCDC_CLK_BUS,
389 .ch[0] = { 389 .ch[0] = {
390 .chan = LCDC_CHAN_MAINLCD, 390 .chan = LCDC_CHAN_MAINLCD,
391 .bpp = 16, 391 .fourcc = V4L2_PIX_FMT_RGB565,
392 .lcd_cfg = mackerel_lcdc_modes, 392 .lcd_cfg = mackerel_lcdc_modes,
393 .num_cfg = ARRAY_SIZE(mackerel_lcdc_modes), 393 .num_cfg = ARRAY_SIZE(mackerel_lcdc_modes),
394 .interface_type = RGB24, 394 .interface_type = RGB24,
@@ -451,7 +451,7 @@ static struct sh_mobile_lcdc_info hdmi_lcdc_info = {
451 .clock_source = LCDC_CLK_EXTERNAL, 451 .clock_source = LCDC_CLK_EXTERNAL,
452 .ch[0] = { 452 .ch[0] = {
453 .chan = LCDC_CHAN_MAINLCD, 453 .chan = LCDC_CHAN_MAINLCD,
454 .bpp = 16, 454 .fourcc = V4L2_PIX_FMT_RGB565,
455 .interface_type = RGB24, 455 .interface_type = RGB24,
456 .clock_divider = 1, 456 .clock_divider = 1,
457 .flags = LCDC_FLAGS_DWPOL, 457 .flags = LCDC_FLAGS_DWPOL,
diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c
index e349c22a0d71..293456d8dcfd 100644
--- a/arch/arm/mach-shmobile/clock-sh7372.c
+++ b/arch/arm/mach-shmobile/clock-sh7372.c
@@ -612,8 +612,8 @@ static struct clk_lookup lookups[] = {
612 CLKDEV_CON_ID("hdmi_clk", &div6_reparent_clks[DIV6_HDMI]), 612 CLKDEV_CON_ID("hdmi_clk", &div6_reparent_clks[DIV6_HDMI]),
613 CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]), 613 CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]),
614 CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSIT]), 614 CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSIT]),
615 CLKDEV_ICK_ID("dsi0p_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]), 615 CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]),
616 CLKDEV_ICK_ID("dsi1p_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]), 616 CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]),
617 617
618 /* MSTP32 clocks */ 618 /* MSTP32 clocks */
619 CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* IIC2 */ 619 CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* IIC2 */
diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c
index 34944d01bf1e..afbead6a6e17 100644
--- a/arch/arm/mach-shmobile/clock-sh73a0.c
+++ b/arch/arm/mach-shmobile/clock-sh73a0.c
@@ -427,8 +427,8 @@ static struct clk_lookup lookups[] = {
427 CLKDEV_CON_ID("sdhi2_clk", &div6_clks[DIV6_SDHI2]), 427 CLKDEV_CON_ID("sdhi2_clk", &div6_clks[DIV6_SDHI2]),
428 CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]), 428 CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]),
429 CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSIT]), 429 CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSIT]),
430 CLKDEV_ICK_ID("dsi0p_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]), 430 CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]),
431 CLKDEV_ICK_ID("dsi1p_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]), 431 CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]),
432 432
433 /* MSTP32 clocks */ 433 /* MSTP32 clocks */
434 CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* I2C2 */ 434 CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* I2C2 */
diff --git a/arch/sh/boards/mach-ap325rxa/setup.c b/arch/sh/boards/mach-ap325rxa/setup.c
index 74d49c01783b..6418e95c2b6b 100644
--- a/arch/sh/boards/mach-ap325rxa/setup.c
+++ b/arch/sh/boards/mach-ap325rxa/setup.c
@@ -207,7 +207,7 @@ static struct sh_mobile_lcdc_info lcdc_info = {
207 .clock_source = LCDC_CLK_EXTERNAL, 207 .clock_source = LCDC_CLK_EXTERNAL,
208 .ch[0] = { 208 .ch[0] = {
209 .chan = LCDC_CHAN_MAINLCD, 209 .chan = LCDC_CHAN_MAINLCD,
210 .bpp = 16, 210 .fourcc = V4L2_PIX_FMT_RGB565,
211 .interface_type = RGB18, 211 .interface_type = RGB18,
212 .clock_divider = 1, 212 .clock_divider = 1,
213 .lcd_cfg = ap325rxa_lcdc_modes, 213 .lcd_cfg = ap325rxa_lcdc_modes,
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index 9a19fb07276c..033ef2ba621f 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -324,7 +324,7 @@ static struct sh_mobile_lcdc_info lcdc_info = {
324 .ch[0] = { 324 .ch[0] = {
325 .interface_type = RGB18, 325 .interface_type = RGB18,
326 .chan = LCDC_CHAN_MAINLCD, 326 .chan = LCDC_CHAN_MAINLCD,
327 .bpp = 16, 327 .fourcc = V4L2_PIX_FMT_RGB565,
328 .lcd_size_cfg = { /* 7.0 inch */ 328 .lcd_size_cfg = { /* 7.0 inch */
329 .width = 152, 329 .width = 152,
330 .height = 91, 330 .height = 91,
diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c
index 5c3c71366848..2a18b06abdaf 100644
--- a/arch/sh/boards/mach-kfr2r09/setup.c
+++ b/arch/sh/boards/mach-kfr2r09/setup.c
@@ -143,7 +143,7 @@ static struct sh_mobile_lcdc_info kfr2r09_sh_lcdc_info = {
143 .clock_source = LCDC_CLK_BUS, 143 .clock_source = LCDC_CLK_BUS,
144 .ch[0] = { 144 .ch[0] = {
145 .chan = LCDC_CHAN_MAINLCD, 145 .chan = LCDC_CHAN_MAINLCD,
146 .bpp = 16, 146 .fourcc = V4L2_PIX_FMT_RGB565,
147 .interface_type = SYS18, 147 .interface_type = SYS18,
148 .clock_divider = 6, 148 .clock_divider = 6,
149 .flags = LCDC_FLAGS_DWPOL, 149 .flags = LCDC_FLAGS_DWPOL,
diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c
index f8f9377d5684..68c3d6f42896 100644
--- a/arch/sh/boards/mach-migor/setup.c
+++ b/arch/sh/boards/mach-migor/setup.c
@@ -241,7 +241,7 @@ static struct sh_mobile_lcdc_info sh_mobile_lcdc_info = {
241 .clock_source = LCDC_CLK_BUS, 241 .clock_source = LCDC_CLK_BUS,
242 .ch[0] = { 242 .ch[0] = {
243 .chan = LCDC_CHAN_MAINLCD, 243 .chan = LCDC_CHAN_MAINLCD,
244 .bpp = 16, 244 .fourcc = V4L2_PIX_FMT_RGB565,
245 .interface_type = RGB16, 245 .interface_type = RGB16,
246 .clock_divider = 2, 246 .clock_divider = 2,
247 .lcd_cfg = migor_lcd_modes, 247 .lcd_cfg = migor_lcd_modes,
@@ -255,7 +255,7 @@ static struct sh_mobile_lcdc_info sh_mobile_lcdc_info = {
255 .clock_source = LCDC_CLK_PERIPHERAL, 255 .clock_source = LCDC_CLK_PERIPHERAL,
256 .ch[0] = { 256 .ch[0] = {
257 .chan = LCDC_CHAN_MAINLCD, 257 .chan = LCDC_CHAN_MAINLCD,
258 .bpp = 16, 258 .fourcc = V4L2_PIX_FMT_RGB565,
259 .interface_type = SYS16A, 259 .interface_type = SYS16A,
260 .clock_divider = 10, 260 .clock_divider = 10,
261 .lcd_cfg = migor_lcd_modes, 261 .lcd_cfg = migor_lcd_modes,
diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c
index 2585733e9bce..036fe1adaef1 100644
--- a/arch/sh/boards/mach-se/7724/setup.c
+++ b/arch/sh/boards/mach-se/7724/setup.c
@@ -179,7 +179,7 @@ static struct sh_mobile_lcdc_info lcdc_info = {
179 .clock_source = LCDC_CLK_EXTERNAL, 179 .clock_source = LCDC_CLK_EXTERNAL,
180 .ch[0] = { 180 .ch[0] = {
181 .chan = LCDC_CHAN_MAINLCD, 181 .chan = LCDC_CHAN_MAINLCD,
182 .bpp = 16, 182 .fourcc = V4L2_PIX_FMT_RGB565,
183 .clock_divider = 1, 183 .clock_divider = 1,
184 .lcd_size_cfg = { /* 7.0 inch */ 184 .lcd_size_cfg = { /* 7.0 inch */
185 .width = 152, 185 .width = 152,
diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c
index 0de598bf66bb..a378c2ce1273 100644
--- a/drivers/media/video/omap/omap_vout.c
+++ b/drivers/media/video/omap/omap_vout.c
@@ -424,7 +424,7 @@ static int omapvid_setup_overlay(struct omap_vout_device *vout,
424 "%s enable=%d addr=%x width=%d\n height=%d color_mode=%d\n" 424 "%s enable=%d addr=%x width=%d\n height=%d color_mode=%d\n"
425 "rotation=%d mirror=%d posx=%d posy=%d out_width = %d \n" 425 "rotation=%d mirror=%d posx=%d posy=%d out_width = %d \n"
426 "out_height=%d rotation_type=%d screen_width=%d\n", 426 "out_height=%d rotation_type=%d screen_width=%d\n",
427 __func__, info.enabled, info.paddr, info.width, info.height, 427 __func__, ovl->is_enabled(ovl), info.paddr, info.width, info.height,
428 info.color_mode, info.rotation, info.mirror, info.pos_x, 428 info.color_mode, info.rotation, info.mirror, info.pos_x,
429 info.pos_y, info.out_width, info.out_height, info.rotation_type, 429 info.pos_y, info.out_width, info.out_height, info.rotation_type,
430 info.screen_width); 430 info.screen_width);
@@ -943,12 +943,8 @@ static int omap_vout_release(struct file *file)
943 /* Disable all the overlay managers connected with this interface */ 943 /* Disable all the overlay managers connected with this interface */
944 for (i = 0; i < ovid->num_overlays; i++) { 944 for (i = 0; i < ovid->num_overlays; i++) {
945 struct omap_overlay *ovl = ovid->overlays[i]; 945 struct omap_overlay *ovl = ovid->overlays[i];
946 if (ovl->manager && ovl->manager->device) { 946 if (ovl->manager && ovl->manager->device)
947 struct omap_overlay_info info; 947 ovl->disable(ovl);
948 ovl->get_overlay_info(ovl, &info);
949 info.enabled = 0;
950 ovl->set_overlay_info(ovl, &info);
951 }
952 } 948 }
953 /* Turn off the pipeline */ 949 /* Turn off the pipeline */
954 ret = omapvid_apply_changes(vout); 950 ret = omapvid_apply_changes(vout);
@@ -1668,7 +1664,6 @@ static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
1668 if (ovl->manager && ovl->manager->device) { 1664 if (ovl->manager && ovl->manager->device) {
1669 struct omap_overlay_info info; 1665 struct omap_overlay_info info;
1670 ovl->get_overlay_info(ovl, &info); 1666 ovl->get_overlay_info(ovl, &info);
1671 info.enabled = 1;
1672 info.paddr = addr; 1667 info.paddr = addr;
1673 if (ovl->set_overlay_info(ovl, &info)) { 1668 if (ovl->set_overlay_info(ovl, &info)) {
1674 ret = -EINVAL; 1669 ret = -EINVAL;
@@ -1687,6 +1682,16 @@ static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
1687 if (ret) 1682 if (ret)
1688 v4l2_err(&vout->vid_dev->v4l2_dev, "failed to change mode\n"); 1683 v4l2_err(&vout->vid_dev->v4l2_dev, "failed to change mode\n");
1689 1684
1685 for (j = 0; j < ovid->num_overlays; j++) {
1686 struct omap_overlay *ovl = ovid->overlays[j];
1687
1688 if (ovl->manager && ovl->manager->device) {
1689 ret = ovl->enable(ovl);
1690 if (ret)
1691 goto streamon_err1;
1692 }
1693 }
1694
1690 ret = 0; 1695 ret = 0;
1691 1696
1692streamon_err1: 1697streamon_err1:
@@ -1716,16 +1721,8 @@ static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
1716 for (j = 0; j < ovid->num_overlays; j++) { 1721 for (j = 0; j < ovid->num_overlays; j++) {
1717 struct omap_overlay *ovl = ovid->overlays[j]; 1722 struct omap_overlay *ovl = ovid->overlays[j];
1718 1723
1719 if (ovl->manager && ovl->manager->device) { 1724 if (ovl->manager && ovl->manager->device)
1720 struct omap_overlay_info info; 1725 ovl->disable(ovl);
1721
1722 ovl->get_overlay_info(ovl, &info);
1723 info.enabled = 0;
1724 ret = ovl->set_overlay_info(ovl, &info);
1725 if (ret)
1726 v4l2_err(&vout->vid_dev->v4l2_dev,
1727 "failed to update overlay info in streamoff\n");
1728 }
1729 } 1726 }
1730 1727
1731 /* Turn of the pipeline */ 1728 /* Turn of the pipeline */
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index acd4ba555e3a..6ca0c407c144 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -2413,7 +2413,6 @@ source "drivers/video/omap/Kconfig"
2413source "drivers/video/omap2/Kconfig" 2413source "drivers/video/omap2/Kconfig"
2414 2414
2415source "drivers/video/backlight/Kconfig" 2415source "drivers/video/backlight/Kconfig"
2416source "drivers/video/display/Kconfig"
2417 2416
2418if VT 2417if VT
2419 source "drivers/video/console/Kconfig" 2418 source "drivers/video/console/Kconfig"
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 9b9d8fff7732..142606814d98 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -13,7 +13,7 @@ fb-objs := $(fb-y)
13 13
14obj-$(CONFIG_VT) += console/ 14obj-$(CONFIG_VT) += console/
15obj-$(CONFIG_LOGO) += logo/ 15obj-$(CONFIG_LOGO) += logo/
16obj-y += backlight/ display/ 16obj-y += backlight/
17 17
18obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o 18obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o
19obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o 19obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c
index 5ea6596dd824..f23cae094f1b 100644
--- a/drivers/video/amifb.c
+++ b/drivers/video/amifb.c
@@ -152,10 +152,10 @@
152 152
153 - hsstrt: Start of horizontal synchronization pulse 153 - hsstrt: Start of horizontal synchronization pulse
154 - hsstop: End of horizontal synchronization pulse 154 - hsstop: End of horizontal synchronization pulse
155 - htotal: Last value on the line (i.e. line length = htotal+1) 155 - htotal: Last value on the line (i.e. line length = htotal + 1)
156 - vsstrt: Start of vertical synchronization pulse 156 - vsstrt: Start of vertical synchronization pulse
157 - vsstop: End of vertical synchronization pulse 157 - vsstop: End of vertical synchronization pulse
158 - vtotal: Last line value (i.e. number of lines = vtotal+1) 158 - vtotal: Last line value (i.e. number of lines = vtotal + 1)
159 - hcenter: Start of vertical retrace for interlace 159 - hcenter: Start of vertical retrace for interlace
160 160
161 You can specify the blanking timings independently. Currently I just set 161 You can specify the blanking timings independently. Currently I just set
@@ -184,7 +184,7 @@
184 clock): 184 clock):
185 185
186 - diwstrt_h: Horizontal start of the visible window 186 - diwstrt_h: Horizontal start of the visible window
187 - diwstop_h: Horizontal stop+1(*) of the visible window 187 - diwstop_h: Horizontal stop + 1(*) of the visible window
188 - diwstrt_v: Vertical start of the visible window 188 - diwstrt_v: Vertical start of the visible window
189 - diwstop_v: Vertical stop of the visible window 189 - diwstop_v: Vertical stop of the visible window
190 - ddfstrt: Horizontal start of display DMA 190 - ddfstrt: Horizontal start of display DMA
@@ -193,7 +193,7 @@
193 193
194 Sprite positioning: 194 Sprite positioning:
195 195
196 - sprstrt_h: Horizontal start-4 of sprite 196 - sprstrt_h: Horizontal start - 4 of sprite
197 - sprstrt_v: Vertical start of sprite 197 - sprstrt_v: Vertical start of sprite
198 198
199 (*) Even Commodore did it wrong in the AGA monitor drivers by not adding 1. 199 (*) Even Commodore did it wrong in the AGA monitor drivers by not adding 1.
@@ -212,21 +212,21 @@
212 display parameters. Here's what I found out: 212 display parameters. Here's what I found out:
213 213
214 - ddfstrt and ddfstop are best aligned to 64 pixels. 214 - ddfstrt and ddfstop are best aligned to 64 pixels.
215 - the chipset needs 64+4 horizontal pixels after the DMA start before the 215 - the chipset needs 64 + 4 horizontal pixels after the DMA start before
216 first pixel is output, so diwstrt_h = ddfstrt+64+4 if you want to 216 the first pixel is output, so diwstrt_h = ddfstrt + 64 + 4 if you want
217 display the first pixel on the line too. Increase diwstrt_h for virtual 217 to display the first pixel on the line too. Increase diwstrt_h for
218 screen panning. 218 virtual screen panning.
219 - the display DMA always fetches 64 pixels at a time (fmode = 3). 219 - the display DMA always fetches 64 pixels at a time (fmode = 3).
220 - ddfstop is ddfstrt+#pixels-64. 220 - ddfstop is ddfstrt+#pixels - 64.
221 - diwstop_h = diwstrt_h+xres+1. Because of the additional 1 this can be 1 221 - diwstop_h = diwstrt_h + xres + 1. Because of the additional 1 this can
222 more than htotal. 222 be 1 more than htotal.
223 - hscroll simply adds a delay to the display output. Smooth horizontal 223 - hscroll simply adds a delay to the display output. Smooth horizontal
224 panning needs an extra 64 pixels on the left to prefetch the pixels that 224 panning needs an extra 64 pixels on the left to prefetch the pixels that
225 `fall off' on the left. 225 `fall off' on the left.
226 - if ddfstrt < 192, the sprite DMA cycles are all stolen by the bitplane 226 - if ddfstrt < 192, the sprite DMA cycles are all stolen by the bitplane
227 DMA, so it's best to make the DMA start as late as possible. 227 DMA, so it's best to make the DMA start as late as possible.
228 - you really don't want to make ddfstrt < 128, since this will steal DMA 228 - you really don't want to make ddfstrt < 128, since this will steal DMA
229 cycles from the other DMA channels (audio, floppy and Chip RAM refresh). 229 cycles from the other DMA channels (audio, floppy and Chip RAM refresh).
230 - I make diwstop_h and diwstop_v as large as possible. 230 - I make diwstop_h and diwstop_v as large as possible.
231 231
232 General dependencies 232 General dependencies
@@ -234,8 +234,8 @@
234 234
235 - all values are SHRES pixel (35ns) 235 - all values are SHRES pixel (35ns)
236 236
237 table 1:fetchstart table 2:prefetch table 3:fetchsize 237 table 1:fetchstart table 2:prefetch table 3:fetchsize
238 ------------------ ---------------- ----------------- 238 ------------------ ---------------- -----------------
239 Pixclock # SHRES|HIRES|LORES # SHRES|HIRES|LORES # SHRES|HIRES|LORES 239 Pixclock # SHRES|HIRES|LORES # SHRES|HIRES|LORES # SHRES|HIRES|LORES
240 -------------#------+-----+------#------+-----+------#------+-----+------ 240 -------------#------+-----+------#------+-----+------#------+-----+------
241 Bus width 1x # 16 | 32 | 64 # 16 | 32 | 64 # 64 | 64 | 64 241 Bus width 1x # 16 | 32 | 64 # 16 | 32 | 64 # 64 | 64 | 64
@@ -245,21 +245,21 @@
245 - chipset needs 4 pixels before the first pixel is output 245 - chipset needs 4 pixels before the first pixel is output
246 - ddfstrt must be aligned to fetchstart (table 1) 246 - ddfstrt must be aligned to fetchstart (table 1)
247 - chipset needs also prefetch (table 2) to get first pixel data, so 247 - chipset needs also prefetch (table 2) to get first pixel data, so
248 ddfstrt = ((diwstrt_h-4) & -fetchstart) - prefetch 248 ddfstrt = ((diwstrt_h - 4) & -fetchstart) - prefetch
249 - for horizontal panning decrease diwstrt_h 249 - for horizontal panning decrease diwstrt_h
250 - the length of a fetchline must be aligned to fetchsize (table 3) 250 - the length of a fetchline must be aligned to fetchsize (table 3)
251 - if fetchstart is smaller than fetchsize, then ddfstrt can a little bit 251 - if fetchstart is smaller than fetchsize, then ddfstrt can a little bit
252 moved to optimize use of dma (useful for OCS/ECS overscan displays) 252 moved to optimize use of dma (useful for OCS/ECS overscan displays)
253 - ddfstop is ddfstrt+ddfsize-fetchsize 253 - ddfstop is ddfstrt + ddfsize - fetchsize
254 - If C= didn't change anything for AGA, then at following positions the 254 - If C= didn't change anything for AGA, then at following positions the
255 dma bus is already used: 255 dma bus is already used:
256 ddfstrt < 48 -> memory refresh 256 ddfstrt < 48 -> memory refresh
257 < 96 -> disk dma 257 < 96 -> disk dma
258 < 160 -> audio dma 258 < 160 -> audio dma
259 < 192 -> sprite 0 dma 259 < 192 -> sprite 0 dma
260 < 416 -> sprite dma (32 per sprite) 260 < 416 -> sprite dma (32 per sprite)
261 - in accordance with the hardware reference manual a hardware stop is at 261 - in accordance with the hardware reference manual a hardware stop is at
262 192, but AGA (ECS?) can go below this. 262 192, but AGA (ECS?) can go below this.
263 263
264 DMA priorities 264 DMA priorities
265 -------------- 265 --------------
@@ -269,7 +269,7 @@
269 the hardware cursor: 269 the hardware cursor:
270 270
271 - if you want to start display DMA too early, you lose the ability to 271 - if you want to start display DMA too early, you lose the ability to
272 do smooth horizontal panning (xpanstep 1 -> 64). 272 do smooth horizontal panning (xpanstep 1 -> 64).
273 - if you want to go even further, you lose the hardware cursor too. 273 - if you want to go even further, you lose the hardware cursor too.
274 274
275 IMHO a hardware cursor is more important for X than horizontal scrolling, 275 IMHO a hardware cursor is more important for X than horizontal scrolling,
@@ -286,8 +286,8 @@
286 Standard VGA timings 286 Standard VGA timings
287 -------------------- 287 --------------------
288 288
289 xres yres left right upper lower hsync vsync 289 xres yres left right upper lower hsync vsync
290 ---- ---- ---- ----- ----- ----- ----- ----- 290 ---- ---- ---- ----- ----- ----- ----- -----
291 80x25 720 400 27 45 35 12 108 2 291 80x25 720 400 27 45 35 12 108 2
292 80x30 720 480 27 45 30 9 108 2 292 80x30 720 480 27 45 30 9 108 2
293 293
@@ -297,8 +297,8 @@
297 297
298 As a comparison, graphics/monitor.h suggests the following: 298 As a comparison, graphics/monitor.h suggests the following:
299 299
300 xres yres left right upper lower hsync vsync 300 xres yres left right upper lower hsync vsync
301 ---- ---- ---- ----- ----- ----- ----- ----- 301 ---- ---- ---- ----- ----- ----- ----- -----
302 302
303 VGA 640 480 52 112 24 19 112 - 2 + 303 VGA 640 480 52 112 24 19 112 - 2 +
304 VGA70 640 400 52 112 27 21 112 - 2 - 304 VGA70 640 400 52 112 27 21 112 - 2 -
@@ -309,10 +309,10 @@
309 309
310 VSYNC HSYNC Vertical size Vertical total 310 VSYNC HSYNC Vertical size Vertical total
311 ----- ----- ------------- -------------- 311 ----- ----- ------------- --------------
312 + + Reserved Reserved 312 + + Reserved Reserved
313 + - 400 414 313 + - 400 414
314 - + 350 362 314 - + 350 362
315 - - 480 496 315 - - 480 496
316 316
317 Source: CL-GD542X Technical Reference Manual, Cirrus Logic, Oct 1992 317 Source: CL-GD542X Technical Reference Manual, Cirrus Logic, Oct 1992
318 318
@@ -326,33 +326,34 @@
326 ----------- 326 -----------
327 327
328 - a scanline is 64 µs long, of which 52.48 µs are visible. This is about 328 - a scanline is 64 µs long, of which 52.48 µs are visible. This is about
329 736 visible 70 ns pixels per line. 329 736 visible 70 ns pixels per line.
330 - we have 625 scanlines, of which 575 are visible (interlaced); after 330 - we have 625 scanlines, of which 575 are visible (interlaced); after
331 rounding this becomes 576. 331 rounding this becomes 576.
332 332
333 RETMA -> NTSC 333 RETMA -> NTSC
334 ------------- 334 -------------
335 335
336 - a scanline is 63.5 µs long, of which 53.5 µs are visible. This is about 336 - a scanline is 63.5 µs long, of which 53.5 µs are visible. This is about
337 736 visible 70 ns pixels per line. 337 736 visible 70 ns pixels per line.
338 - we have 525 scanlines, of which 485 are visible (interlaced); after 338 - we have 525 scanlines, of which 485 are visible (interlaced); after
339 rounding this becomes 484. 339 rounding this becomes 484.
340 340
341 Thus if you want a PAL compatible display, you have to do the following: 341 Thus if you want a PAL compatible display, you have to do the following:
342 342
343 - set the FB_SYNC_BROADCAST flag to indicate that standard broadcast 343 - set the FB_SYNC_BROADCAST flag to indicate that standard broadcast
344 timings are to be used. 344 timings are to be used.
345 - make sure upper_margin+yres+lower_margin+vsync_len = 625 for an 345 - make sure upper_margin + yres + lower_margin + vsync_len = 625 for an
346 interlaced, 312 for a non-interlaced and 156 for a doublescanned 346 interlaced, 312 for a non-interlaced and 156 for a doublescanned
347 display. 347 display.
348 - make sure left_margin+xres+right_margin+hsync_len = 1816 for a SHRES, 348 - make sure left_margin + xres + right_margin + hsync_len = 1816 for a
349 908 for a HIRES and 454 for a LORES display. 349 SHRES, 908 for a HIRES and 454 for a LORES display.
350 - the left visible part begins at 360 (SHRES; HIRES:180, LORES:90), 350 - the left visible part begins at 360 (SHRES; HIRES:180, LORES:90),
351 left_margin+2*hsync_len must be greater or equal. 351 left_margin + 2 * hsync_len must be greater or equal.
352 - the upper visible part begins at 48 (interlaced; non-interlaced:24, 352 - the upper visible part begins at 48 (interlaced; non-interlaced:24,
353 doublescanned:12), upper_margin+2*vsync_len must be greater or equal. 353 doublescanned:12), upper_margin + 2 * vsync_len must be greater or
354 equal.
354 - ami_encode_var() calculates margins with a hsync of 5320 ns and a vsync 355 - ami_encode_var() calculates margins with a hsync of 5320 ns and a vsync
355 of 4 scanlines 356 of 4 scanlines
356 357
357 The settings for a NTSC compatible display are straightforward. 358 The settings for a NTSC compatible display are straightforward.
358 359
@@ -361,7 +362,7 @@
361 anything about horizontal/vertical synchronization nor refresh rates. 362 anything about horizontal/vertical synchronization nor refresh rates.
362 363
363 364
364 -- Geert -- 365 -- Geert --
365 366
366*******************************************************************************/ 367*******************************************************************************/
367 368
@@ -540,45 +541,45 @@ static u_short maxfmode, chipset;
540 * Various macros 541 * Various macros
541 */ 542 */
542 543
543#define up2(v) (((v)+1) & -2) 544#define up2(v) (((v) + 1) & -2)
544#define down2(v) ((v) & -2) 545#define down2(v) ((v) & -2)
545#define div2(v) ((v)>>1) 546#define div2(v) ((v)>>1)
546#define mod2(v) ((v) & 1) 547#define mod2(v) ((v) & 1)
547 548
548#define up4(v) (((v)+3) & -4) 549#define up4(v) (((v) + 3) & -4)
549#define down4(v) ((v) & -4) 550#define down4(v) ((v) & -4)
550#define mul4(v) ((v)<<2) 551#define mul4(v) ((v) << 2)
551#define div4(v) ((v)>>2) 552#define div4(v) ((v)>>2)
552#define mod4(v) ((v) & 3) 553#define mod4(v) ((v) & 3)
553 554
554#define up8(v) (((v)+7) & -8) 555#define up8(v) (((v) + 7) & -8)
555#define down8(v) ((v) & -8) 556#define down8(v) ((v) & -8)
556#define div8(v) ((v)>>3) 557#define div8(v) ((v)>>3)
557#define mod8(v) ((v) & 7) 558#define mod8(v) ((v) & 7)
558 559
559#define up16(v) (((v)+15) & -16) 560#define up16(v) (((v) + 15) & -16)
560#define down16(v) ((v) & -16) 561#define down16(v) ((v) & -16)
561#define div16(v) ((v)>>4) 562#define div16(v) ((v)>>4)
562#define mod16(v) ((v) & 15) 563#define mod16(v) ((v) & 15)
563 564
564#define up32(v) (((v)+31) & -32) 565#define up32(v) (((v) + 31) & -32)
565#define down32(v) ((v) & -32) 566#define down32(v) ((v) & -32)
566#define div32(v) ((v)>>5) 567#define div32(v) ((v)>>5)
567#define mod32(v) ((v) & 31) 568#define mod32(v) ((v) & 31)
568 569
569#define up64(v) (((v)+63) & -64) 570#define up64(v) (((v) + 63) & -64)
570#define down64(v) ((v) & -64) 571#define down64(v) ((v) & -64)
571#define div64(v) ((v)>>6) 572#define div64(v) ((v)>>6)
572#define mod64(v) ((v) & 63) 573#define mod64(v) ((v) & 63)
573 574
574#define upx(x,v) (((v)+(x)-1) & -(x)) 575#define upx(x, v) (((v) + (x) - 1) & -(x))
575#define downx(x,v) ((v) & -(x)) 576#define downx(x, v) ((v) & -(x))
576#define modx(x,v) ((v) & ((x)-1)) 577#define modx(x, v) ((v) & ((x) - 1))
577 578
578/* if x1 is not a constant, this macro won't make real sense :-) */ 579/* if x1 is not a constant, this macro won't make real sense :-) */
579#ifdef __mc68000__ 580#ifdef __mc68000__
580#define DIVUL(x1, x2) ({int res; asm("divul %1,%2,%3": "=d" (res): \ 581#define DIVUL(x1, x2) ({int res; asm("divul %1,%2,%3": "=d" (res): \
581 "d" (x2), "d" ((long)((x1)/0x100000000ULL)), "0" ((long)(x1))); res;}) 582 "d" (x2), "d" ((long)((x1) / 0x100000000ULL)), "0" ((long)(x1))); res;})
582#else 583#else
583/* We know a bit about the numbers, so we can do it this way */ 584/* We know a bit about the numbers, so we can do it this way */
584#define DIVUL(x1, x2) ((((long)((unsigned long long)x1 >> 8) / x2) << 8) + \ 585#define DIVUL(x1, x2) ((((long)((unsigned long long)x1 >> 8) / x2) << 8) + \
@@ -607,7 +608,7 @@ static u_short maxfmode, chipset;
607#define VIDEOMEMSIZE_ECS_1M (393216) /* ECS (1MB) : max 1024*768*16 */ 608#define VIDEOMEMSIZE_ECS_1M (393216) /* ECS (1MB) : max 1024*768*16 */
608#define VIDEOMEMSIZE_OCS (262144) /* OCS : max ca. 800*600*16 */ 609#define VIDEOMEMSIZE_OCS (262144) /* OCS : max ca. 800*600*16 */
609 610
610#define SPRITEMEMSIZE (64*64/4) /* max 64*64*4 */ 611#define SPRITEMEMSIZE (64 * 64 / 4) /* max 64*64*4 */
611#define DUMMYSPRITEMEMSIZE (8) 612#define DUMMYSPRITEMEMSIZE (8)
612static u_long spritememory; 613static u_long spritememory;
613 614
@@ -634,9 +635,9 @@ static u_long min_fstrt = 192;
634 * Copper Instructions 635 * Copper Instructions
635 */ 636 */
636 637
637#define CMOVE(val, reg) (CUSTOM_OFS(reg)<<16 | (val)) 638#define CMOVE(val, reg) (CUSTOM_OFS(reg) << 16 | (val))
638#define CMOVE2(val, reg) ((CUSTOM_OFS(reg)+2)<<16 | (val)) 639#define CMOVE2(val, reg) ((CUSTOM_OFS(reg) + 2) << 16 | (val))
639#define CWAIT(x, y) (((y) & 0x1fe)<<23 | ((x) & 0x7f0)<<13 | 0x0001fffe) 640#define CWAIT(x, y) (((y) & 0x1fe) << 23 | ((x) & 0x7f0) << 13 | 0x0001fffe)
640#define CEND (0xfffffffe) 641#define CEND (0xfffffffe)
641 642
642 643
@@ -709,7 +710,7 @@ static u_short *lofsprite, *shfsprite, *dummysprite;
709 * Current Video Mode 710 * Current Video Mode
710 */ 711 */
711 712
712static struct amifb_par { 713struct amifb_par {
713 714
714 /* General Values */ 715 /* General Values */
715 716
@@ -772,15 +773,6 @@ static struct amifb_par {
772 /* Additional AGA Hardware Registers */ 773 /* Additional AGA Hardware Registers */
773 774
774 u_short fmode; /* vmode */ 775 u_short fmode; /* vmode */
775} currentpar;
776
777
778static struct fb_info fb_info = {
779 .fix = {
780 .id = "Amiga ",
781 .visual = FB_VISUAL_PSEUDOCOLOR,
782 .accel = FB_ACCEL_AMIGABLITT
783 }
784}; 776};
785 777
786 778
@@ -820,116 +812,123 @@ static u_short is_lace = 0; /* Screen is laced */
820 812
821static struct fb_videomode ami_modedb[] __initdata = { 813static struct fb_videomode ami_modedb[] __initdata = {
822 814
823 /* 815 /*
824 * AmigaOS Video Modes 816 * AmigaOS Video Modes
825 * 817 *
826 * If you change these, make sure to update DEFMODE_* as well! 818 * If you change these, make sure to update DEFMODE_* as well!
827 */ 819 */
828 820
829 { 821 {
830 /* 640x200, 15 kHz, 60 Hz (NTSC) */ 822 /* 640x200, 15 kHz, 60 Hz (NTSC) */
831 "ntsc", 60, 640, 200, TAG_HIRES, 106, 86, 44, 16, 76, 2, 823 "ntsc", 60, 640, 200, TAG_HIRES, 106, 86, 44, 16, 76, 2,
832 FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 824 FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
833 }, { 825 }, {
834 /* 640x400, 15 kHz, 60 Hz interlaced (NTSC) */ 826 /* 640x400, 15 kHz, 60 Hz interlaced (NTSC) */
835 "ntsc-lace", 60, 640, 400, TAG_HIRES, 106, 86, 88, 33, 76, 4, 827 "ntsc-lace", 60, 640, 400, TAG_HIRES, 106, 86, 88, 33, 76, 4,
836 FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 828 FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
837 }, { 829 }, {
838 /* 640x256, 15 kHz, 50 Hz (PAL) */ 830 /* 640x256, 15 kHz, 50 Hz (PAL) */
839 "pal", 50, 640, 256, TAG_HIRES, 106, 86, 40, 14, 76, 2, 831 "pal", 50, 640, 256, TAG_HIRES, 106, 86, 40, 14, 76, 2,
840 FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 832 FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
841 }, { 833 }, {
842 /* 640x512, 15 kHz, 50 Hz interlaced (PAL) */ 834 /* 640x512, 15 kHz, 50 Hz interlaced (PAL) */
843 "pal-lace", 50, 640, 512, TAG_HIRES, 106, 86, 80, 29, 76, 4, 835 "pal-lace", 50, 640, 512, TAG_HIRES, 106, 86, 80, 29, 76, 4,
844 FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 836 FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
845 }, { 837 }, {
846 /* 640x480, 29 kHz, 57 Hz */ 838 /* 640x480, 29 kHz, 57 Hz */
847 "multiscan", 57, 640, 480, TAG_SHRES, 96, 112, 29, 8, 72, 8, 839 "multiscan", 57, 640, 480, TAG_SHRES, 96, 112, 29, 8, 72, 8,
848 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 840 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
849 }, { 841 }, {
850 /* 640x960, 29 kHz, 57 Hz interlaced */ 842 /* 640x960, 29 kHz, 57 Hz interlaced */
851 "multiscan-lace", 57, 640, 960, TAG_SHRES, 96, 112, 58, 16, 72, 16, 843 "multiscan-lace", 57, 640, 960, TAG_SHRES, 96, 112, 58, 16, 72,
852 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 844 16,
853 }, { 845 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
854 /* 640x200, 15 kHz, 72 Hz */ 846 }, {
855 "euro36", 72, 640, 200, TAG_HIRES, 92, 124, 6, 6, 52, 5, 847 /* 640x200, 15 kHz, 72 Hz */
856 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 848 "euro36", 72, 640, 200, TAG_HIRES, 92, 124, 6, 6, 52, 5,
857 }, { 849 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
858 /* 640x400, 15 kHz, 72 Hz interlaced */ 850 }, {
859 "euro36-lace", 72, 640, 400, TAG_HIRES, 92, 124, 12, 12, 52, 10, 851 /* 640x400, 15 kHz, 72 Hz interlaced */
860 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 852 "euro36-lace", 72, 640, 400, TAG_HIRES, 92, 124, 12, 12, 52,
861 }, { 853 10,
862 /* 640x400, 29 kHz, 68 Hz */ 854 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
863 "euro72", 68, 640, 400, TAG_SHRES, 164, 92, 9, 9, 80, 8, 855 }, {
864 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 856 /* 640x400, 29 kHz, 68 Hz */
865 }, { 857 "euro72", 68, 640, 400, TAG_SHRES, 164, 92, 9, 9, 80, 8,
866 /* 640x800, 29 kHz, 68 Hz interlaced */ 858 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
867 "euro72-lace", 68, 640, 800, TAG_SHRES, 164, 92, 18, 18, 80, 16, 859 }, {
868 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 860 /* 640x800, 29 kHz, 68 Hz interlaced */
869 }, { 861 "euro72-lace", 68, 640, 800, TAG_SHRES, 164, 92, 18, 18, 80,
870 /* 800x300, 23 kHz, 70 Hz */ 862 16,
871 "super72", 70, 800, 300, TAG_SHRES, 212, 140, 10, 11, 80, 7, 863 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
872 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 864 }, {
873 }, { 865 /* 800x300, 23 kHz, 70 Hz */
874 /* 800x600, 23 kHz, 70 Hz interlaced */ 866 "super72", 70, 800, 300, TAG_SHRES, 212, 140, 10, 11, 80, 7,
875 "super72-lace", 70, 800, 600, TAG_SHRES, 212, 140, 20, 22, 80, 14, 867 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
876 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 868 }, {
877 }, { 869 /* 800x600, 23 kHz, 70 Hz interlaced */
878 /* 640x200, 27 kHz, 57 Hz doublescan */ 870 "super72-lace", 70, 800, 600, TAG_SHRES, 212, 140, 20, 22, 80,
879 "dblntsc", 57, 640, 200, TAG_SHRES, 196, 124, 18, 17, 80, 4, 871 14,
880 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP 872 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
881 }, { 873 }, {
882 /* 640x400, 27 kHz, 57 Hz */ 874 /* 640x200, 27 kHz, 57 Hz doublescan */
883 "dblntsc-ff", 57, 640, 400, TAG_SHRES, 196, 124, 36, 35, 80, 7, 875 "dblntsc", 57, 640, 200, TAG_SHRES, 196, 124, 18, 17, 80, 4,
884 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 876 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
885 }, { 877 }, {
886 /* 640x800, 27 kHz, 57 Hz interlaced */ 878 /* 640x400, 27 kHz, 57 Hz */
887 "dblntsc-lace", 57, 640, 800, TAG_SHRES, 196, 124, 72, 70, 80, 14, 879 "dblntsc-ff", 57, 640, 400, TAG_SHRES, 196, 124, 36, 35, 80, 7,
888 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 880 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
889 }, { 881 }, {
890 /* 640x256, 27 kHz, 47 Hz doublescan */ 882 /* 640x800, 27 kHz, 57 Hz interlaced */
891 "dblpal", 47, 640, 256, TAG_SHRES, 196, 124, 14, 13, 80, 4, 883 "dblntsc-lace", 57, 640, 800, TAG_SHRES, 196, 124, 72, 70, 80,
892 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP 884 14,
893 }, { 885 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
894 /* 640x512, 27 kHz, 47 Hz */ 886 }, {
895 "dblpal-ff", 47, 640, 512, TAG_SHRES, 196, 124, 28, 27, 80, 7, 887 /* 640x256, 27 kHz, 47 Hz doublescan */
896 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 888 "dblpal", 47, 640, 256, TAG_SHRES, 196, 124, 14, 13, 80, 4,
897 }, { 889 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
898 /* 640x1024, 27 kHz, 47 Hz interlaced */ 890 }, {
899 "dblpal-lace", 47, 640, 1024, TAG_SHRES, 196, 124, 56, 54, 80, 14, 891 /* 640x512, 27 kHz, 47 Hz */
900 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 892 "dblpal-ff", 47, 640, 512, TAG_SHRES, 196, 124, 28, 27, 80, 7,
901 }, 893 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
902 894 }, {
903 /* 895 /* 640x1024, 27 kHz, 47 Hz interlaced */
904 * VGA Video Modes 896 "dblpal-lace", 47, 640, 1024, TAG_SHRES, 196, 124, 56, 54, 80,
905 */ 897 14,
906 898 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
907 { 899 },
908 /* 640x480, 31 kHz, 60 Hz (VGA) */ 900
909 "vga", 60, 640, 480, TAG_SHRES, 64, 96, 30, 9, 112, 2, 901 /*
910 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 902 * VGA Video Modes
911 }, { 903 */
912 /* 640x400, 31 kHz, 70 Hz (VGA) */ 904
913 "vga70", 70, 640, 400, TAG_SHRES, 64, 96, 35, 12, 112, 2, 905 {
914 FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 906 /* 640x480, 31 kHz, 60 Hz (VGA) */
915 }, 907 "vga", 60, 640, 480, TAG_SHRES, 64, 96, 30, 9, 112, 2,
908 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
909 }, {
910 /* 640x400, 31 kHz, 70 Hz (VGA) */
911 "vga70", 70, 640, 400, TAG_SHRES, 64, 96, 35, 12, 112, 2,
912 FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT,
913 FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
914 },
916 915
917#if 0 916#if 0
918 917
919 /* 918 /*
920 * A2024 video modes 919 * A2024 video modes
921 * These modes don't work yet because there's no A2024 driver. 920 * These modes don't work yet because there's no A2024 driver.
922 */ 921 */
923 922
924 { 923 {
925 /* 1024x800, 10 Hz */ 924 /* 1024x800, 10 Hz */
926 "a2024-10", 10, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0, 925 "a2024-10", 10, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
927 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 926 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
928 }, { 927 }, {
929 /* 1024x800, 15 Hz */ 928 /* 1024x800, 15 Hz */
930 "a2024-15", 15, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0, 929 "a2024-15", 15, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
931 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 930 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
932 } 931 }
933#endif 932#endif
934}; 933};
935 934
@@ -953,6 +952,11 @@ static int round_down_bpp = 1; /* for mode probing */
953static int amifb_ilbm = 0; /* interleaved or normal bitplanes */ 952static int amifb_ilbm = 0; /* interleaved or normal bitplanes */
954static int amifb_inverse = 0; 953static int amifb_inverse = 0;
955 954
955static u32 amifb_hfmin __initdata; /* monitor hfreq lower limit (Hz) */
956static u32 amifb_hfmax __initdata; /* monitor hfreq upper limit (Hz) */
957static u16 amifb_vfmin __initdata; /* monitor vfreq lower limit (Hz) */
958static u16 amifb_vfmax __initdata; /* monitor vfreq upper limit (Hz) */
959
956 960
957 /* 961 /*
958 * Macros for the conversion from real world values to hardware register 962 * Macros for the conversion from real world values to hardware register
@@ -992,19 +996,20 @@ static int amifb_inverse = 0;
992/* bplcon1 (smooth scrolling) */ 996/* bplcon1 (smooth scrolling) */
993 997
994#define hscroll2hw(hscroll) \ 998#define hscroll2hw(hscroll) \
995 (((hscroll)<<12 & 0x3000) | ((hscroll)<<8 & 0xc300) | \ 999 (((hscroll) << 12 & 0x3000) | ((hscroll) << 8 & 0xc300) | \
996 ((hscroll)<<4 & 0x0c00) | ((hscroll)<<2 & 0x00f0) | ((hscroll)>>2 & 0x000f)) 1000 ((hscroll) << 4 & 0x0c00) | ((hscroll) << 2 & 0x00f0) | \
1001 ((hscroll)>>2 & 0x000f))
997 1002
998/* diwstrt/diwstop/diwhigh (visible display window) */ 1003/* diwstrt/diwstop/diwhigh (visible display window) */
999 1004
1000#define diwstrt2hw(diwstrt_h, diwstrt_v) \ 1005#define diwstrt2hw(diwstrt_h, diwstrt_v) \
1001 (((diwstrt_v)<<7 & 0xff00) | ((diwstrt_h)>>2 & 0x00ff)) 1006 (((diwstrt_v) << 7 & 0xff00) | ((diwstrt_h)>>2 & 0x00ff))
1002#define diwstop2hw(diwstop_h, diwstop_v) \ 1007#define diwstop2hw(diwstop_h, diwstop_v) \
1003 (((diwstop_v)<<7 & 0xff00) | ((diwstop_h)>>2 & 0x00ff)) 1008 (((diwstop_v) << 7 & 0xff00) | ((diwstop_h)>>2 & 0x00ff))
1004#define diwhigh2hw(diwstrt_h, diwstrt_v, diwstop_h, diwstop_v) \ 1009#define diwhigh2hw(diwstrt_h, diwstrt_v, diwstop_h, diwstop_v) \
1005 (((diwstop_h)<<3 & 0x2000) | ((diwstop_h)<<11 & 0x1800) | \ 1010 (((diwstop_h) << 3 & 0x2000) | ((diwstop_h) << 11 & 0x1800) | \
1006 ((diwstop_v)>>1 & 0x0700) | ((diwstrt_h)>>5 & 0x0020) | \ 1011 ((diwstop_v)>>1 & 0x0700) | ((diwstrt_h)>>5 & 0x0020) | \
1007 ((diwstrt_h)<<3 & 0x0018) | ((diwstrt_v)>>9 & 0x0007)) 1012 ((diwstrt_h) << 3 & 0x0018) | ((diwstrt_v)>>9 & 0x0007))
1008 1013
1009/* ddfstrt/ddfstop (display DMA) */ 1014/* ddfstrt/ddfstop (display DMA) */
1010 1015
@@ -1015,38 +1020,39 @@ static int amifb_inverse = 0;
1015 1020
1016#define hsstrt2hw(hsstrt) (div8(hsstrt)) 1021#define hsstrt2hw(hsstrt) (div8(hsstrt))
1017#define hsstop2hw(hsstop) (div8(hsstop)) 1022#define hsstop2hw(hsstop) (div8(hsstop))
1018#define htotal2hw(htotal) (div8(htotal)-1) 1023#define htotal2hw(htotal) (div8(htotal) - 1)
1019#define vsstrt2hw(vsstrt) (div2(vsstrt)) 1024#define vsstrt2hw(vsstrt) (div2(vsstrt))
1020#define vsstop2hw(vsstop) (div2(vsstop)) 1025#define vsstop2hw(vsstop) (div2(vsstop))
1021#define vtotal2hw(vtotal) (div2(vtotal)-1) 1026#define vtotal2hw(vtotal) (div2(vtotal) - 1)
1022#define hcenter2hw(htotal) (div8(htotal)) 1027#define hcenter2hw(htotal) (div8(htotal))
1023 1028
1024/* hbstrt/hbstop/vbstrt/vbstop (blanking timings) */ 1029/* hbstrt/hbstop/vbstrt/vbstop (blanking timings) */
1025 1030
1026#define hbstrt2hw(hbstrt) (((hbstrt)<<8 & 0x0700) | ((hbstrt)>>3 & 0x00ff)) 1031#define hbstrt2hw(hbstrt) (((hbstrt) << 8 & 0x0700) | ((hbstrt)>>3 & 0x00ff))
1027#define hbstop2hw(hbstop) (((hbstop)<<8 & 0x0700) | ((hbstop)>>3 & 0x00ff)) 1032#define hbstop2hw(hbstop) (((hbstop) << 8 & 0x0700) | ((hbstop)>>3 & 0x00ff))
1028#define vbstrt2hw(vbstrt) (div2(vbstrt)) 1033#define vbstrt2hw(vbstrt) (div2(vbstrt))
1029#define vbstop2hw(vbstop) (div2(vbstop)) 1034#define vbstop2hw(vbstop) (div2(vbstop))
1030 1035
1031/* colour */ 1036/* colour */
1032 1037
1033#define rgb2hw8_high(red, green, blue) \ 1038#define rgb2hw8_high(red, green, blue) \
1034 (((red & 0xf0)<<4) | (green & 0xf0) | ((blue & 0xf0)>>4)) 1039 (((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0)>>4))
1035#define rgb2hw8_low(red, green, blue) \ 1040#define rgb2hw8_low(red, green, blue) \
1036 (((red & 0x0f)<<8) | ((green & 0x0f)<<4) | (blue & 0x0f)) 1041 (((red & 0x0f) << 8) | ((green & 0x0f) << 4) | (blue & 0x0f))
1037#define rgb2hw4(red, green, blue) \ 1042#define rgb2hw4(red, green, blue) \
1038 (((red & 0xf0)<<4) | (green & 0xf0) | ((blue & 0xf0)>>4)) 1043 (((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0)>>4))
1039#define rgb2hw2(red, green, blue) \ 1044#define rgb2hw2(red, green, blue) \
1040 (((red & 0xc0)<<4) | (green & 0xc0) | ((blue & 0xc0)>>4)) 1045 (((red & 0xc0) << 4) | (green & 0xc0) | ((blue & 0xc0)>>4))
1041 1046
1042/* sprpos/sprctl (sprite positioning) */ 1047/* sprpos/sprctl (sprite positioning) */
1043 1048
1044#define spr2hw_pos(start_v, start_h) \ 1049#define spr2hw_pos(start_v, start_h) \
1045 (((start_v)<<7&0xff00) | ((start_h)>>3&0x00ff)) 1050 (((start_v) << 7 & 0xff00) | ((start_h)>>3 & 0x00ff))
1046#define spr2hw_ctl(start_v, start_h, stop_v) \ 1051#define spr2hw_ctl(start_v, start_h, stop_v) \
1047 (((stop_v)<<7&0xff00) | ((start_v)>>4&0x0040) | ((stop_v)>>5&0x0020) | \ 1052 (((stop_v) << 7 & 0xff00) | ((start_v)>>4 & 0x0040) | \
1048 ((start_h)<<3&0x0018) | ((start_v)>>7&0x0004) | ((stop_v)>>8&0x0002) | \ 1053 ((stop_v)>>5 & 0x0020) | ((start_h) << 3 & 0x0018) | \
1049 ((start_h)>>2&0x0001)) 1054 ((start_v)>>7 & 0x0004) | ((stop_v)>>8 & 0x0002) | \
1055 ((start_h)>>2 & 0x0001))
1050 1056
1051/* get current vertical position of beam */ 1057/* get current vertical position of beam */
1052#define get_vbpos() ((u_short)((*(u_long volatile *)&custom.vposr >> 7) & 0xffe)) 1058#define get_vbpos() ((u_short)((*(u_long volatile *)&custom.vposr >> 7) & 0xffe))
@@ -1055,7 +1061,7 @@ static int amifb_inverse = 0;
1055 * Copper Initialisation List 1061 * Copper Initialisation List
1056 */ 1062 */
1057 1063
1058#define COPINITSIZE (sizeof(copins)*40) 1064#define COPINITSIZE (sizeof(copins) * 40)
1059 1065
1060enum { 1066enum {
1061 cip_bplcon0 1067 cip_bplcon0
@@ -1066,7 +1072,7 @@ enum {
1066 * Don't change the order, build_copper()/rebuild_copper() rely on this 1072 * Don't change the order, build_copper()/rebuild_copper() rely on this
1067 */ 1073 */
1068 1074
1069#define COPLISTSIZE (sizeof(copins)*64) 1075#define COPLISTSIZE (sizeof(copins) * 64)
1070 1076
1071enum { 1077enum {
1072 cop_wait, cop_bplcon0, 1078 cop_wait, cop_bplcon0,
@@ -1108,82 +1114,1199 @@ static u_short sprfetchmode[3] = {
1108}; 1114};
1109 1115
1110 1116
1117/* --------------------------- Hardware routines --------------------------- */
1118
1111 /* 1119 /*
1112 * Interface used by the world 1120 * Get the video params out of `var'. If a value doesn't fit, round
1121 * it up, if it's too big, return -EINVAL.
1113 */ 1122 */
1114 1123
1115int amifb_setup(char*); 1124static int ami_decode_var(struct fb_var_screeninfo *var, struct amifb_par *par,
1125 const struct fb_info *info)
1126{
1127 u_short clk_shift, line_shift;
1128 u_long maxfetchstop, fstrt, fsize, fconst, xres_n, yres_n;
1129 u_int htotal, vtotal;
1116 1130
1117static int amifb_check_var(struct fb_var_screeninfo *var, 1131 /*
1118 struct fb_info *info); 1132 * Find a matching Pixel Clock
1119static int amifb_set_par(struct fb_info *info); 1133 */
1120static int amifb_setcolreg(unsigned regno, unsigned red, unsigned green,
1121 unsigned blue, unsigned transp,
1122 struct fb_info *info);
1123static int amifb_blank(int blank, struct fb_info *info);
1124static int amifb_pan_display(struct fb_var_screeninfo *var,
1125 struct fb_info *info);
1126static void amifb_fillrect(struct fb_info *info,
1127 const struct fb_fillrect *rect);
1128static void amifb_copyarea(struct fb_info *info,
1129 const struct fb_copyarea *region);
1130static void amifb_imageblit(struct fb_info *info,
1131 const struct fb_image *image);
1132static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg);
1133 1134
1135 for (clk_shift = TAG_SHRES; clk_shift <= TAG_LORES; clk_shift++)
1136 if (var->pixclock <= pixclock[clk_shift])
1137 break;
1138 if (clk_shift > TAG_LORES) {
1139 DPRINTK("pixclock too high\n");
1140 return -EINVAL;
1141 }
1142 par->clk_shift = clk_shift;
1134 1143
1135 /* 1144 /*
1136 * Interface to the low level console driver 1145 * Check the Geometry Values
1137 */ 1146 */
1138 1147
1139static void amifb_deinit(struct platform_device *pdev); 1148 if ((par->xres = var->xres) < 64)
1149 par->xres = 64;
1150 if ((par->yres = var->yres) < 64)
1151 par->yres = 64;
1152 if ((par->vxres = var->xres_virtual) < par->xres)
1153 par->vxres = par->xres;
1154 if ((par->vyres = var->yres_virtual) < par->yres)
1155 par->vyres = par->yres;
1156
1157 par->bpp = var->bits_per_pixel;
1158 if (!var->nonstd) {
1159 if (par->bpp < 1)
1160 par->bpp = 1;
1161 if (par->bpp > maxdepth[clk_shift]) {
1162 if (round_down_bpp && maxdepth[clk_shift])
1163 par->bpp = maxdepth[clk_shift];
1164 else {
1165 DPRINTK("invalid bpp\n");
1166 return -EINVAL;
1167 }
1168 }
1169 } else if (var->nonstd == FB_NONSTD_HAM) {
1170 if (par->bpp < 6)
1171 par->bpp = 6;
1172 if (par->bpp != 6) {
1173 if (par->bpp < 8)
1174 par->bpp = 8;
1175 if (par->bpp != 8 || !IS_AGA) {
1176 DPRINTK("invalid bpp for ham mode\n");
1177 return -EINVAL;
1178 }
1179 }
1180 } else {
1181 DPRINTK("unknown nonstd mode\n");
1182 return -EINVAL;
1183 }
1140 1184
1141 /* 1185 /*
1142 * Internal routines 1186 * FB_VMODE_SMOOTH_XPAN will be cleared, if one of the folloing
1187 * checks failed and smooth scrolling is not possible
1143 */ 1188 */
1144 1189
1145static int flash_cursor(void); 1190 par->vmode = var->vmode | FB_VMODE_SMOOTH_XPAN;
1146static irqreturn_t amifb_interrupt(int irq, void *dev_id); 1191 switch (par->vmode & FB_VMODE_MASK) {
1147static u_long chipalloc(u_long size); 1192 case FB_VMODE_INTERLACED:
1148static void chipfree(void); 1193 line_shift = 0;
1194 break;
1195 case FB_VMODE_NONINTERLACED:
1196 line_shift = 1;
1197 break;
1198 case FB_VMODE_DOUBLE:
1199 if (!IS_AGA) {
1200 DPRINTK("double mode only possible with aga\n");
1201 return -EINVAL;
1202 }
1203 line_shift = 2;
1204 break;
1205 default:
1206 DPRINTK("unknown video mode\n");
1207 return -EINVAL;
1208 break;
1209 }
1210 par->line_shift = line_shift;
1149 1211
1150 /* 1212 /*
1151 * Hardware routines 1213 * Vertical and Horizontal Timings
1152 */ 1214 */
1153 1215
1154static int ami_decode_var(struct fb_var_screeninfo *var, 1216 xres_n = par->xres << clk_shift;
1155 struct amifb_par *par); 1217 yres_n = par->yres << line_shift;
1156static int ami_encode_var(struct fb_var_screeninfo *var, 1218 par->htotal = down8((var->left_margin + par->xres + var->right_margin +
1157 struct amifb_par *par); 1219 var->hsync_len) << clk_shift);
1158static void ami_pan_var(struct fb_var_screeninfo *var); 1220 par->vtotal =
1159static int ami_update_par(void); 1221 down2(((var->upper_margin + par->yres + var->lower_margin +
1160static void ami_update_display(void); 1222 var->vsync_len) << line_shift) + 1);
1161static void ami_init_display(void);
1162static void ami_do_blank(void);
1163static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix);
1164static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data);
1165static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data);
1166static int ami_get_cursorstate(struct fb_cursorstate *state);
1167static int ami_set_cursorstate(struct fb_cursorstate *state);
1168static void ami_set_sprite(void);
1169static void ami_init_copper(void);
1170static void ami_reinit_copper(void);
1171static void ami_build_copper(void);
1172static void ami_rebuild_copper(void);
1173 1223
1224 if (IS_AGA)
1225 par->bplcon3 = sprpixmode[clk_shift];
1226 else
1227 par->bplcon3 = 0;
1228 if (var->sync & FB_SYNC_BROADCAST) {
1229 par->diwstop_h = par->htotal -
1230 ((var->right_margin - var->hsync_len) << clk_shift);
1231 if (IS_AGA)
1232 par->diwstop_h += mod4(var->hsync_len);
1233 else
1234 par->diwstop_h = down4(par->diwstop_h);
1235
1236 par->diwstrt_h = par->diwstop_h - xres_n;
1237 par->diwstop_v = par->vtotal -
1238 ((var->lower_margin - var->vsync_len) << line_shift);
1239 par->diwstrt_v = par->diwstop_v - yres_n;
1240 if (par->diwstop_h >= par->htotal + 8) {
1241 DPRINTK("invalid diwstop_h\n");
1242 return -EINVAL;
1243 }
1244 if (par->diwstop_v > par->vtotal) {
1245 DPRINTK("invalid diwstop_v\n");
1246 return -EINVAL;
1247 }
1248
1249 if (!IS_OCS) {
1250 /* Initialize sync with some reasonable values for pwrsave */
1251 par->hsstrt = 160;
1252 par->hsstop = 320;
1253 par->vsstrt = 30;
1254 par->vsstop = 34;
1255 } else {
1256 par->hsstrt = 0;
1257 par->hsstop = 0;
1258 par->vsstrt = 0;
1259 par->vsstop = 0;
1260 }
1261 if (par->vtotal > (PAL_VTOTAL + NTSC_VTOTAL) / 2) {
1262 /* PAL video mode */
1263 if (par->htotal != PAL_HTOTAL) {
1264 DPRINTK("htotal invalid for pal\n");
1265 return -EINVAL;
1266 }
1267 if (par->diwstrt_h < PAL_DIWSTRT_H) {
1268 DPRINTK("diwstrt_h too low for pal\n");
1269 return -EINVAL;
1270 }
1271 if (par->diwstrt_v < PAL_DIWSTRT_V) {
1272 DPRINTK("diwstrt_v too low for pal\n");
1273 return -EINVAL;
1274 }
1275 htotal = PAL_HTOTAL>>clk_shift;
1276 vtotal = PAL_VTOTAL>>1;
1277 if (!IS_OCS) {
1278 par->beamcon0 = BMC0_PAL;
1279 par->bplcon3 |= BPC3_BRDRBLNK;
1280 } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
1281 AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
1282 par->beamcon0 = BMC0_PAL;
1283 par->hsstop = 1;
1284 } else if (amiga_vblank != 50) {
1285 DPRINTK("pal not supported by this chipset\n");
1286 return -EINVAL;
1287 }
1288 } else {
1289 /* NTSC video mode
1290 * In the AGA chipset seems to be hardware bug with BPC3_BRDRBLNK
1291 * and NTSC activated, so than better let diwstop_h <= 1812
1292 */
1293 if (par->htotal != NTSC_HTOTAL) {
1294 DPRINTK("htotal invalid for ntsc\n");
1295 return -EINVAL;
1296 }
1297 if (par->diwstrt_h < NTSC_DIWSTRT_H) {
1298 DPRINTK("diwstrt_h too low for ntsc\n");
1299 return -EINVAL;
1300 }
1301 if (par->diwstrt_v < NTSC_DIWSTRT_V) {
1302 DPRINTK("diwstrt_v too low for ntsc\n");
1303 return -EINVAL;
1304 }
1305 htotal = NTSC_HTOTAL>>clk_shift;
1306 vtotal = NTSC_VTOTAL>>1;
1307 if (!IS_OCS) {
1308 par->beamcon0 = 0;
1309 par->bplcon3 |= BPC3_BRDRBLNK;
1310 } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
1311 AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
1312 par->beamcon0 = 0;
1313 par->hsstop = 1;
1314 } else if (amiga_vblank != 60) {
1315 DPRINTK("ntsc not supported by this chipset\n");
1316 return -EINVAL;
1317 }
1318 }
1319 if (IS_OCS) {
1320 if (par->diwstrt_h >= 1024 || par->diwstop_h < 1024 ||
1321 par->diwstrt_v >= 512 || par->diwstop_v < 256) {
1322 DPRINTK("invalid position for display on ocs\n");
1323 return -EINVAL;
1324 }
1325 }
1326 } else if (!IS_OCS) {
1327 /* Programmable video mode */
1328 par->hsstrt = var->right_margin << clk_shift;
1329 par->hsstop = (var->right_margin + var->hsync_len) << clk_shift;
1330 par->diwstop_h = par->htotal - mod8(par->hsstrt) + 8 - (1 << clk_shift);
1331 if (!IS_AGA)
1332 par->diwstop_h = down4(par->diwstop_h) - 16;
1333 par->diwstrt_h = par->diwstop_h - xres_n;
1334 par->hbstop = par->diwstrt_h + 4;
1335 par->hbstrt = par->diwstop_h + 4;
1336 if (par->hbstrt >= par->htotal + 8)
1337 par->hbstrt -= par->htotal;
1338 par->hcenter = par->hsstrt + (par->htotal >> 1);
1339 par->vsstrt = var->lower_margin << line_shift;
1340 par->vsstop = (var->lower_margin + var->vsync_len) << line_shift;
1341 par->diwstop_v = par->vtotal;
1342 if ((par->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
1343 par->diwstop_v -= 2;
1344 par->diwstrt_v = par->diwstop_v - yres_n;
1345 par->vbstop = par->diwstrt_v - 2;
1346 par->vbstrt = par->diwstop_v - 2;
1347 if (par->vtotal > 2048) {
1348 DPRINTK("vtotal too high\n");
1349 return -EINVAL;
1350 }
1351 if (par->htotal > 2048) {
1352 DPRINTK("htotal too high\n");
1353 return -EINVAL;
1354 }
1355 par->bplcon3 |= BPC3_EXTBLKEN;
1356 par->beamcon0 = BMC0_HARDDIS | BMC0_VARVBEN | BMC0_LOLDIS |
1357 BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARBEAMEN |
1358 BMC0_PAL | BMC0_VARCSYEN;
1359 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
1360 par->beamcon0 |= BMC0_HSYTRUE;
1361 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
1362 par->beamcon0 |= BMC0_VSYTRUE;
1363 if (var->sync & FB_SYNC_COMP_HIGH_ACT)
1364 par->beamcon0 |= BMC0_CSYTRUE;
1365 htotal = par->htotal>>clk_shift;
1366 vtotal = par->vtotal>>1;
1367 } else {
1368 DPRINTK("only broadcast modes possible for ocs\n");
1369 return -EINVAL;
1370 }
1371
1372 /*
1373 * Checking the DMA timing
1374 */
1375
1376 fconst = 16 << maxfmode << clk_shift;
1377
1378 /*
1379 * smallest window start value without turn off other dma cycles
1380 * than sprite1-7, unless you change min_fstrt
1381 */
1382
1383
1384 fsize = ((maxfmode + clk_shift <= 1) ? fconst : 64);
1385 fstrt = downx(fconst, par->diwstrt_h - 4) - fsize;
1386 if (fstrt < min_fstrt) {
1387 DPRINTK("fetch start too low\n");
1388 return -EINVAL;
1389 }
1390
1391 /*
1392 * smallest window start value where smooth scrolling is possible
1393 */
1394
1395 fstrt = downx(fconst, par->diwstrt_h - fconst + (1 << clk_shift) - 4) -
1396 fsize;
1397 if (fstrt < min_fstrt)
1398 par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
1399
1400 maxfetchstop = down16(par->htotal - 80);
1401
1402 fstrt = downx(fconst, par->diwstrt_h - 4) - 64 - fconst;
1403 fsize = upx(fconst, xres_n +
1404 modx(fconst, downx(1 << clk_shift, par->diwstrt_h - 4)));
1405 if (fstrt + fsize > maxfetchstop)
1406 par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
1407
1408 fsize = upx(fconst, xres_n);
1409 if (fstrt + fsize > maxfetchstop) {
1410 DPRINTK("fetch stop too high\n");
1411 return -EINVAL;
1412 }
1413
1414 if (maxfmode + clk_shift <= 1) {
1415 fsize = up64(xres_n + fconst - 1);
1416 if (min_fstrt + fsize - 64 > maxfetchstop)
1417 par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
1418
1419 fsize = up64(xres_n);
1420 if (min_fstrt + fsize - 64 > maxfetchstop) {
1421 DPRINTK("fetch size too high\n");
1422 return -EINVAL;
1423 }
1424
1425 fsize -= 64;
1426 } else
1427 fsize -= fconst;
1428
1429 /*
1430 * Check if there is enough time to update the bitplane pointers for ywrap
1431 */
1432
1433 if (par->htotal - fsize - 64 < par->bpp * 64)
1434 par->vmode &= ~FB_VMODE_YWRAP;
1435
1436 /*
1437 * Bitplane calculations and check the Memory Requirements
1438 */
1439
1440 if (amifb_ilbm) {
1441 par->next_plane = div8(upx(16 << maxfmode, par->vxres));
1442 par->next_line = par->bpp * par->next_plane;
1443 if (par->next_line * par->vyres > info->fix.smem_len) {
1444 DPRINTK("too few video mem\n");
1445 return -EINVAL;
1446 }
1447 } else {
1448 par->next_line = div8(upx(16 << maxfmode, par->vxres));
1449 par->next_plane = par->vyres * par->next_line;
1450 if (par->next_plane * par->bpp > info->fix.smem_len) {
1451 DPRINTK("too few video mem\n");
1452 return -EINVAL;
1453 }
1454 }
1455
1456 /*
1457 * Hardware Register Values
1458 */
1459
1460 par->bplcon0 = BPC0_COLOR | bplpixmode[clk_shift];
1461 if (!IS_OCS)
1462 par->bplcon0 |= BPC0_ECSENA;
1463 if (par->bpp == 8)
1464 par->bplcon0 |= BPC0_BPU3;
1465 else
1466 par->bplcon0 |= par->bpp << 12;
1467 if (var->nonstd == FB_NONSTD_HAM)
1468 par->bplcon0 |= BPC0_HAM;
1469 if (var->sync & FB_SYNC_EXT)
1470 par->bplcon0 |= BPC0_ERSY;
1471
1472 if (IS_AGA)
1473 par->fmode = bplfetchmode[maxfmode];
1474
1475 switch (par->vmode & FB_VMODE_MASK) {
1476 case FB_VMODE_INTERLACED:
1477 par->bplcon0 |= BPC0_LACE;
1478 break;
1479 case FB_VMODE_DOUBLE:
1480 if (IS_AGA)
1481 par->fmode |= FMODE_SSCAN2 | FMODE_BSCAN2;
1482 break;
1483 }
1484
1485 if (!((par->vmode ^ var->vmode) & FB_VMODE_YWRAP)) {
1486 par->xoffset = var->xoffset;
1487 par->yoffset = var->yoffset;
1488 if (par->vmode & FB_VMODE_YWRAP) {
1489 if (par->xoffset || par->yoffset < 0 ||
1490 par->yoffset >= par->vyres)
1491 par->xoffset = par->yoffset = 0;
1492 } else {
1493 if (par->xoffset < 0 ||
1494 par->xoffset > upx(16 << maxfmode, par->vxres - par->xres) ||
1495 par->yoffset < 0 || par->yoffset > par->vyres - par->yres)
1496 par->xoffset = par->yoffset = 0;
1497 }
1498 } else
1499 par->xoffset = par->yoffset = 0;
1500
1501 par->crsr.crsr_x = par->crsr.crsr_y = 0;
1502 par->crsr.spot_x = par->crsr.spot_y = 0;
1503 par->crsr.height = par->crsr.width = 0;
1504
1505 return 0;
1506}
1507
1508 /*
1509 * Fill the `var' structure based on the values in `par' and maybe
1510 * other values read out of the hardware.
1511 */
1512
1513static void ami_encode_var(struct fb_var_screeninfo *var,
1514 struct amifb_par *par)
1515{
1516 u_short clk_shift, line_shift;
1517
1518 memset(var, 0, sizeof(struct fb_var_screeninfo));
1519
1520 clk_shift = par->clk_shift;
1521 line_shift = par->line_shift;
1522
1523 var->xres = par->xres;
1524 var->yres = par->yres;
1525 var->xres_virtual = par->vxres;
1526 var->yres_virtual = par->vyres;
1527 var->xoffset = par->xoffset;
1528 var->yoffset = par->yoffset;
1529
1530 var->bits_per_pixel = par->bpp;
1531 var->grayscale = 0;
1532
1533 var->red.offset = 0;
1534 var->red.msb_right = 0;
1535 var->red.length = par->bpp;
1536 if (par->bplcon0 & BPC0_HAM)
1537 var->red.length -= 2;
1538 var->blue = var->green = var->red;
1539 var->transp.offset = 0;
1540 var->transp.length = 0;
1541 var->transp.msb_right = 0;
1542
1543 if (par->bplcon0 & BPC0_HAM)
1544 var->nonstd = FB_NONSTD_HAM;
1545 else
1546 var->nonstd = 0;
1547 var->activate = 0;
1548
1549 var->height = -1;
1550 var->width = -1;
1551
1552 var->pixclock = pixclock[clk_shift];
1553
1554 if (IS_AGA && par->fmode & FMODE_BSCAN2)
1555 var->vmode = FB_VMODE_DOUBLE;
1556 else if (par->bplcon0 & BPC0_LACE)
1557 var->vmode = FB_VMODE_INTERLACED;
1558 else
1559 var->vmode = FB_VMODE_NONINTERLACED;
1560
1561 if (!IS_OCS && par->beamcon0 & BMC0_VARBEAMEN) {
1562 var->hsync_len = (par->hsstop - par->hsstrt)>>clk_shift;
1563 var->right_margin = par->hsstrt>>clk_shift;
1564 var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
1565 var->vsync_len = (par->vsstop - par->vsstrt)>>line_shift;
1566 var->lower_margin = par->vsstrt>>line_shift;
1567 var->upper_margin = (par->vtotal>>line_shift) - var->yres - var->lower_margin - var->vsync_len;
1568 var->sync = 0;
1569 if (par->beamcon0 & BMC0_HSYTRUE)
1570 var->sync |= FB_SYNC_HOR_HIGH_ACT;
1571 if (par->beamcon0 & BMC0_VSYTRUE)
1572 var->sync |= FB_SYNC_VERT_HIGH_ACT;
1573 if (par->beamcon0 & BMC0_CSYTRUE)
1574 var->sync |= FB_SYNC_COMP_HIGH_ACT;
1575 } else {
1576 var->sync = FB_SYNC_BROADCAST;
1577 var->hsync_len = (152>>clk_shift) + mod4(par->diwstop_h);
1578 var->right_margin = ((par->htotal - down4(par->diwstop_h))>>clk_shift) + var->hsync_len;
1579 var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
1580 var->vsync_len = 4>>line_shift;
1581 var->lower_margin = ((par->vtotal - par->diwstop_v)>>line_shift) + var->vsync_len;
1582 var->upper_margin = (((par->vtotal - 2)>>line_shift) + 1) - var->yres -
1583 var->lower_margin - var->vsync_len;
1584 }
1585
1586 if (par->bplcon0 & BPC0_ERSY)
1587 var->sync |= FB_SYNC_EXT;
1588 if (par->vmode & FB_VMODE_YWRAP)
1589 var->vmode |= FB_VMODE_YWRAP;
1590}
1591
1592
1593 /*
1594 * Update hardware
1595 */
1596
1597static void ami_update_par(struct fb_info *info)
1598{
1599 struct amifb_par *par = info->par;
1600 short clk_shift, vshift, fstrt, fsize, fstop, fconst, shift, move, mod;
1601
1602 clk_shift = par->clk_shift;
1603
1604 if (!(par->vmode & FB_VMODE_SMOOTH_XPAN))
1605 par->xoffset = upx(16 << maxfmode, par->xoffset);
1606
1607 fconst = 16 << maxfmode << clk_shift;
1608 vshift = modx(16 << maxfmode, par->xoffset);
1609 fstrt = par->diwstrt_h - (vshift << clk_shift) - 4;
1610 fsize = (par->xres + vshift) << clk_shift;
1611 shift = modx(fconst, fstrt);
1612 move = downx(2 << maxfmode, div8(par->xoffset));
1613 if (maxfmode + clk_shift > 1) {
1614 fstrt = downx(fconst, fstrt) - 64;
1615 fsize = upx(fconst, fsize);
1616 fstop = fstrt + fsize - fconst;
1617 } else {
1618 mod = fstrt = downx(fconst, fstrt) - fconst;
1619 fstop = fstrt + upx(fconst, fsize) - 64;
1620 fsize = up64(fsize);
1621 fstrt = fstop - fsize + 64;
1622 if (fstrt < min_fstrt) {
1623 fstop += min_fstrt - fstrt;
1624 fstrt = min_fstrt;
1625 }
1626 move = move - div8((mod - fstrt)>>clk_shift);
1627 }
1628 mod = par->next_line - div8(fsize>>clk_shift);
1629 par->ddfstrt = fstrt;
1630 par->ddfstop = fstop;
1631 par->bplcon1 = hscroll2hw(shift);
1632 par->bpl2mod = mod;
1633 if (par->bplcon0 & BPC0_LACE)
1634 par->bpl2mod += par->next_line;
1635 if (IS_AGA && (par->fmode & FMODE_BSCAN2))
1636 par->bpl1mod = -div8(fsize>>clk_shift);
1637 else
1638 par->bpl1mod = par->bpl2mod;
1639
1640 if (par->yoffset) {
1641 par->bplpt0 = info->fix.smem_start +
1642 par->next_line * par->yoffset + move;
1643 if (par->vmode & FB_VMODE_YWRAP) {
1644 if (par->yoffset > par->vyres - par->yres) {
1645 par->bplpt0wrap = info->fix.smem_start + move;
1646 if (par->bplcon0 & BPC0_LACE &&
1647 mod2(par->diwstrt_v + par->vyres -
1648 par->yoffset))
1649 par->bplpt0wrap += par->next_line;
1650 }
1651 }
1652 } else
1653 par->bplpt0 = info->fix.smem_start + move;
1654
1655 if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v))
1656 par->bplpt0 += par->next_line;
1657}
1658
1659
1660 /*
1661 * Pan or Wrap the Display
1662 *
1663 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
1664 * in `var'.
1665 */
1666
1667static void ami_pan_var(struct fb_var_screeninfo *var, struct fb_info *info)
1668{
1669 struct amifb_par *par = info->par;
1670
1671 par->xoffset = var->xoffset;
1672 par->yoffset = var->yoffset;
1673 if (var->vmode & FB_VMODE_YWRAP)
1674 par->vmode |= FB_VMODE_YWRAP;
1675 else
1676 par->vmode &= ~FB_VMODE_YWRAP;
1677
1678 do_vmode_pan = 0;
1679 ami_update_par(info);
1680 do_vmode_pan = 1;
1681}
1682
1683
1684static void ami_update_display(const struct amifb_par *par)
1685{
1686 custom.bplcon1 = par->bplcon1;
1687 custom.bpl1mod = par->bpl1mod;
1688 custom.bpl2mod = par->bpl2mod;
1689 custom.ddfstrt = ddfstrt2hw(par->ddfstrt);
1690 custom.ddfstop = ddfstop2hw(par->ddfstop);
1691}
1692
1693 /*
1694 * Change the video mode (called by VBlank interrupt)
1695 */
1696
1697static void ami_init_display(const struct amifb_par *par)
1698{
1699 int i;
1700
1701 custom.bplcon0 = par->bplcon0 & ~BPC0_LACE;
1702 custom.bplcon2 = (IS_OCS ? 0 : BPC2_KILLEHB) | BPC2_PF2P2 | BPC2_PF1P2;
1703 if (!IS_OCS) {
1704 custom.bplcon3 = par->bplcon3;
1705 if (IS_AGA)
1706 custom.bplcon4 = BPC4_ESPRM4 | BPC4_OSPRM4;
1707 if (par->beamcon0 & BMC0_VARBEAMEN) {
1708 custom.htotal = htotal2hw(par->htotal);
1709 custom.hbstrt = hbstrt2hw(par->hbstrt);
1710 custom.hbstop = hbstop2hw(par->hbstop);
1711 custom.hsstrt = hsstrt2hw(par->hsstrt);
1712 custom.hsstop = hsstop2hw(par->hsstop);
1713 custom.hcenter = hcenter2hw(par->hcenter);
1714 custom.vtotal = vtotal2hw(par->vtotal);
1715 custom.vbstrt = vbstrt2hw(par->vbstrt);
1716 custom.vbstop = vbstop2hw(par->vbstop);
1717 custom.vsstrt = vsstrt2hw(par->vsstrt);
1718 custom.vsstop = vsstop2hw(par->vsstop);
1719 }
1720 }
1721 if (!IS_OCS || par->hsstop)
1722 custom.beamcon0 = par->beamcon0;
1723 if (IS_AGA)
1724 custom.fmode = par->fmode;
1725
1726 /*
1727 * The minimum period for audio depends on htotal
1728 */
1729
1730 amiga_audio_min_period = div16(par->htotal);
1731
1732 is_lace = par->bplcon0 & BPC0_LACE ? 1 : 0;
1733#if 1
1734 if (is_lace) {
1735 i = custom.vposr >> 15;
1736 } else {
1737 custom.vposw = custom.vposr | 0x8000;
1738 i = 1;
1739 }
1740#else
1741 i = 1;
1742 custom.vposw = custom.vposr | 0x8000;
1743#endif
1744 custom.cop2lc = (u_short *)ZTWO_PADDR(copdisplay.list[currentcop][i]);
1745}
1746
1747 /*
1748 * (Un)Blank the screen (called by VBlank interrupt)
1749 */
1750
1751static void ami_do_blank(const struct amifb_par *par)
1752{
1753#if defined(CONFIG_FB_AMIGA_AGA)
1754 u_short bplcon3 = par->bplcon3;
1755#endif
1756 u_char red, green, blue;
1757
1758 if (do_blank > 0) {
1759 custom.dmacon = DMAF_RASTER | DMAF_SPRITE;
1760 red = green = blue = 0;
1761 if (!IS_OCS && do_blank > 1) {
1762 switch (do_blank) {
1763 case FB_BLANK_VSYNC_SUSPEND:
1764 custom.hsstrt = hsstrt2hw(par->hsstrt);
1765 custom.hsstop = hsstop2hw(par->hsstop);
1766 custom.vsstrt = vsstrt2hw(par->vtotal + 4);
1767 custom.vsstop = vsstop2hw(par->vtotal + 4);
1768 break;
1769 case FB_BLANK_HSYNC_SUSPEND:
1770 custom.hsstrt = hsstrt2hw(par->htotal + 16);
1771 custom.hsstop = hsstop2hw(par->htotal + 16);
1772 custom.vsstrt = vsstrt2hw(par->vsstrt);
1773 custom.vsstop = vsstrt2hw(par->vsstop);
1774 break;
1775 case FB_BLANK_POWERDOWN:
1776 custom.hsstrt = hsstrt2hw(par->htotal + 16);
1777 custom.hsstop = hsstop2hw(par->htotal + 16);
1778 custom.vsstrt = vsstrt2hw(par->vtotal + 4);
1779 custom.vsstop = vsstop2hw(par->vtotal + 4);
1780 break;
1781 }
1782 if (!(par->beamcon0 & BMC0_VARBEAMEN)) {
1783 custom.htotal = htotal2hw(par->htotal);
1784 custom.vtotal = vtotal2hw(par->vtotal);
1785 custom.beamcon0 = BMC0_HARDDIS | BMC0_VARBEAMEN |
1786 BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARCSYEN;
1787 }
1788 }
1789 } else {
1790 custom.dmacon = DMAF_SETCLR | DMAF_RASTER | DMAF_SPRITE;
1791 red = red0;
1792 green = green0;
1793 blue = blue0;
1794 if (!IS_OCS) {
1795 custom.hsstrt = hsstrt2hw(par->hsstrt);
1796 custom.hsstop = hsstop2hw(par->hsstop);
1797 custom.vsstrt = vsstrt2hw(par->vsstrt);
1798 custom.vsstop = vsstop2hw(par->vsstop);
1799 custom.beamcon0 = par->beamcon0;
1800 }
1801 }
1802#if defined(CONFIG_FB_AMIGA_AGA)
1803 if (IS_AGA) {
1804 custom.bplcon3 = bplcon3;
1805 custom.color[0] = rgb2hw8_high(red, green, blue);
1806 custom.bplcon3 = bplcon3 | BPC3_LOCT;
1807 custom.color[0] = rgb2hw8_low(red, green, blue);
1808 custom.bplcon3 = bplcon3;
1809 } else
1810#endif
1811#if defined(CONFIG_FB_AMIGA_ECS)
1812 if (par->bplcon0 & BPC0_SHRES) {
1813 u_short color, mask;
1814 int i;
1815
1816 mask = 0x3333;
1817 color = rgb2hw2(red, green, blue);
1818 for (i = 12; i >= 0; i -= 4)
1819 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
1820 mask <<= 2; color >>= 2;
1821 for (i = 3; i >= 0; i--)
1822 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
1823 } else
1824#endif
1825 custom.color[0] = rgb2hw4(red, green, blue);
1826 is_blanked = do_blank > 0 ? do_blank : 0;
1827}
1828
1829static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix,
1830 const struct amifb_par *par)
1831{
1832 fix->crsr_width = fix->crsr_xsize = par->crsr.width;
1833 fix->crsr_height = fix->crsr_ysize = par->crsr.height;
1834 fix->crsr_color1 = 17;
1835 fix->crsr_color2 = 18;
1836 return 0;
1837}
1838
1839static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var,
1840 u_char __user *data,
1841 const struct amifb_par *par)
1842{
1843 register u_short *lspr, *sspr;
1844#ifdef __mc68000__
1845 register u_long datawords asm ("d2");
1846#else
1847 register u_long datawords;
1848#endif
1849 register short delta;
1850 register u_char color;
1851 short height, width, bits, words;
1852 int size, alloc;
1853
1854 size = par->crsr.height * par->crsr.width;
1855 alloc = var->height * var->width;
1856 var->height = par->crsr.height;
1857 var->width = par->crsr.width;
1858 var->xspot = par->crsr.spot_x;
1859 var->yspot = par->crsr.spot_y;
1860 if (size > var->height * var->width)
1861 return -ENAMETOOLONG;
1862 if (!access_ok(VERIFY_WRITE, data, size))
1863 return -EFAULT;
1864 delta = 1 << par->crsr.fmode;
1865 lspr = lofsprite + (delta << 1);
1866 if (par->bplcon0 & BPC0_LACE)
1867 sspr = shfsprite + (delta << 1);
1868 else
1869 sspr = NULL;
1870 for (height = (short)var->height - 1; height >= 0; height--) {
1871 bits = 0; words = delta; datawords = 0;
1872 for (width = (short)var->width - 1; width >= 0; width--) {
1873 if (bits == 0) {
1874 bits = 16; --words;
1875#ifdef __mc68000__
1876 asm volatile ("movew %1@(%3:w:2),%0 ; swap %0 ; movew %1@+,%0"
1877 : "=d" (datawords), "=a" (lspr) : "1" (lspr), "d" (delta));
1878#else
1879 datawords = (*(lspr + delta) << 16) | (*lspr++);
1880#endif
1881 }
1882 --bits;
1883#ifdef __mc68000__
1884 asm volatile (
1885 "clrb %0 ; swap %1 ; lslw #1,%1 ; roxlb #1,%0 ; "
1886 "swap %1 ; lslw #1,%1 ; roxlb #1,%0"
1887 : "=d" (color), "=d" (datawords) : "1" (datawords));
1888#else
1889 color = (((datawords >> 30) & 2)
1890 | ((datawords >> 15) & 1));
1891 datawords <<= 1;
1892#endif
1893 put_user(color, data++);
1894 }
1895 if (bits > 0) {
1896 --words; ++lspr;
1897 }
1898 while (--words >= 0)
1899 ++lspr;
1900#ifdef __mc68000__
1901 asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
1902 : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
1903#else
1904 lspr += delta;
1905 if (sspr) {
1906 u_short *tmp = lspr;
1907 lspr = sspr;
1908 sspr = tmp;
1909 }
1910#endif
1911 }
1912 return 0;
1913}
1914
1915static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var,
1916 u_char __user *data, struct amifb_par *par)
1917{
1918 register u_short *lspr, *sspr;
1919#ifdef __mc68000__
1920 register u_long datawords asm ("d2");
1921#else
1922 register u_long datawords;
1923#endif
1924 register short delta;
1925 u_short fmode;
1926 short height, width, bits, words;
1927
1928 if (!var->width)
1929 return -EINVAL;
1930 else if (var->width <= 16)
1931 fmode = TAG_FMODE_1;
1932 else if (var->width <= 32)
1933 fmode = TAG_FMODE_2;
1934 else if (var->width <= 64)
1935 fmode = TAG_FMODE_4;
1936 else
1937 return -EINVAL;
1938 if (fmode > maxfmode)
1939 return -EINVAL;
1940 if (!var->height)
1941 return -EINVAL;
1942 if (!access_ok(VERIFY_READ, data, var->width * var->height))
1943 return -EFAULT;
1944 delta = 1 << fmode;
1945 lofsprite = shfsprite = (u_short *)spritememory;
1946 lspr = lofsprite + (delta << 1);
1947 if (par->bplcon0 & BPC0_LACE) {
1948 if (((var->height + 4) << fmode << 2) > SPRITEMEMSIZE)
1949 return -EINVAL;
1950 memset(lspr, 0, (var->height + 4) << fmode << 2);
1951 shfsprite += ((var->height + 5)&-2) << fmode;
1952 sspr = shfsprite + (delta << 1);
1953 } else {
1954 if (((var->height + 2) << fmode << 2) > SPRITEMEMSIZE)
1955 return -EINVAL;
1956 memset(lspr, 0, (var->height + 2) << fmode << 2);
1957 sspr = NULL;
1958 }
1959 for (height = (short)var->height - 1; height >= 0; height--) {
1960 bits = 16; words = delta; datawords = 0;
1961 for (width = (short)var->width - 1; width >= 0; width--) {
1962 unsigned long tdata = 0;
1963 get_user(tdata, data);
1964 data++;
1965#ifdef __mc68000__
1966 asm volatile (
1967 "lsrb #1,%2 ; roxlw #1,%0 ; swap %0 ; "
1968 "lsrb #1,%2 ; roxlw #1,%0 ; swap %0"
1969 : "=d" (datawords)
1970 : "0" (datawords), "d" (tdata));
1971#else
1972 datawords = ((datawords << 1) & 0xfffefffe);
1973 datawords |= tdata & 1;
1974 datawords |= (tdata & 2) << (16 - 1);
1975#endif
1976 if (--bits == 0) {
1977 bits = 16; --words;
1978#ifdef __mc68000__
1979 asm volatile ("swap %2 ; movew %2,%0@(%3:w:2) ; swap %2 ; movew %2,%0@+"
1980 : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta));
1981#else
1982 *(lspr + delta) = (u_short) (datawords >> 16);
1983 *lspr++ = (u_short) (datawords & 0xffff);
1984#endif
1985 }
1986 }
1987 if (bits < 16) {
1988 --words;
1989#ifdef __mc68000__
1990 asm volatile (
1991 "swap %2 ; lslw %4,%2 ; movew %2,%0@(%3:w:2) ; "
1992 "swap %2 ; lslw %4,%2 ; movew %2,%0@+"
1993 : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta), "d" (bits));
1994#else
1995 *(lspr + delta) = (u_short) (datawords >> (16 + bits));
1996 *lspr++ = (u_short) ((datawords & 0x0000ffff) >> bits);
1997#endif
1998 }
1999 while (--words >= 0) {
2000#ifdef __mc68000__
2001 asm volatile ("moveql #0,%%d0 ; movew %%d0,%0@(%2:w:2) ; movew %%d0,%0@+"
2002 : "=a" (lspr) : "0" (lspr), "d" (delta) : "d0");
2003#else
2004 *(lspr + delta) = 0;
2005 *lspr++ = 0;
2006#endif
2007 }
2008#ifdef __mc68000__
2009 asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
2010 : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
2011#else
2012 lspr += delta;
2013 if (sspr) {
2014 u_short *tmp = lspr;
2015 lspr = sspr;
2016 sspr = tmp;
2017 }
2018#endif
2019 }
2020 par->crsr.height = var->height;
2021 par->crsr.width = var->width;
2022 par->crsr.spot_x = var->xspot;
2023 par->crsr.spot_y = var->yspot;
2024 par->crsr.fmode = fmode;
2025 if (IS_AGA) {
2026 par->fmode &= ~(FMODE_SPAGEM | FMODE_SPR32);
2027 par->fmode |= sprfetchmode[fmode];
2028 custom.fmode = par->fmode;
2029 }
2030 return 0;
2031}
2032
2033static int ami_get_cursorstate(struct fb_cursorstate *state,
2034 const struct amifb_par *par)
2035{
2036 state->xoffset = par->crsr.crsr_x;
2037 state->yoffset = par->crsr.crsr_y;
2038 state->mode = cursormode;
2039 return 0;
2040}
2041
2042static int ami_set_cursorstate(struct fb_cursorstate *state,
2043 struct amifb_par *par)
2044{
2045 par->crsr.crsr_x = state->xoffset;
2046 par->crsr.crsr_y = state->yoffset;
2047 if ((cursormode = state->mode) == FB_CURSOR_OFF)
2048 cursorstate = -1;
2049 do_cursor = 1;
2050 return 0;
2051}
2052
2053static void ami_set_sprite(const struct amifb_par *par)
2054{
2055 copins *copl, *cops;
2056 u_short hs, vs, ve;
2057 u_long pl, ps, pt;
2058 short mx, my;
2059
2060 cops = copdisplay.list[currentcop][0];
2061 copl = copdisplay.list[currentcop][1];
2062 ps = pl = ZTWO_PADDR(dummysprite);
2063 mx = par->crsr.crsr_x - par->crsr.spot_x;
2064 my = par->crsr.crsr_y - par->crsr.spot_y;
2065 if (!(par->vmode & FB_VMODE_YWRAP)) {
2066 mx -= par->xoffset;
2067 my -= par->yoffset;
2068 }
2069 if (!is_blanked && cursorstate > 0 && par->crsr.height > 0 &&
2070 mx > -(short)par->crsr.width && mx < par->xres &&
2071 my > -(short)par->crsr.height && my < par->yres) {
2072 pl = ZTWO_PADDR(lofsprite);
2073 hs = par->diwstrt_h + (mx << par->clk_shift) - 4;
2074 vs = par->diwstrt_v + (my << par->line_shift);
2075 ve = vs + (par->crsr.height << par->line_shift);
2076 if (par->bplcon0 & BPC0_LACE) {
2077 ps = ZTWO_PADDR(shfsprite);
2078 lofsprite[0] = spr2hw_pos(vs, hs);
2079 shfsprite[0] = spr2hw_pos(vs + 1, hs);
2080 if (mod2(vs)) {
2081 lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
2082 shfsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs + 1, hs, ve + 1);
2083 pt = pl; pl = ps; ps = pt;
2084 } else {
2085 lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve + 1);
2086 shfsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs + 1, hs, ve);
2087 }
2088 } else {
2089 lofsprite[0] = spr2hw_pos(vs, hs) | (IS_AGA && (par->fmode & FMODE_BSCAN2) ? 0x80 : 0);
2090 lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
2091 }
2092 }
2093 copl[cop_spr0ptrh].w[1] = highw(pl);
2094 copl[cop_spr0ptrl].w[1] = loww(pl);
2095 if (par->bplcon0 & BPC0_LACE) {
2096 cops[cop_spr0ptrh].w[1] = highw(ps);
2097 cops[cop_spr0ptrl].w[1] = loww(ps);
2098 }
2099}
2100
2101
2102 /*
2103 * Initialise the Copper Initialisation List
2104 */
2105
2106static void __init ami_init_copper(void)
2107{
2108 copins *cop = copdisplay.init;
2109 u_long p;
2110 int i;
2111
2112 if (!IS_OCS) {
2113 (cop++)->l = CMOVE(BPC0_COLOR | BPC0_SHRES | BPC0_ECSENA, bplcon0);
2114 (cop++)->l = CMOVE(0x0181, diwstrt);
2115 (cop++)->l = CMOVE(0x0281, diwstop);
2116 (cop++)->l = CMOVE(0x0000, diwhigh);
2117 } else
2118 (cop++)->l = CMOVE(BPC0_COLOR, bplcon0);
2119 p = ZTWO_PADDR(dummysprite);
2120 for (i = 0; i < 8; i++) {
2121 (cop++)->l = CMOVE(0, spr[i].pos);
2122 (cop++)->l = CMOVE(highw(p), sprpt[i]);
2123 (cop++)->l = CMOVE2(loww(p), sprpt[i]);
2124 }
2125
2126 (cop++)->l = CMOVE(IF_SETCLR | IF_COPER, intreq);
2127 copdisplay.wait = cop;
2128 (cop++)->l = CEND;
2129 (cop++)->l = CMOVE(0, copjmp2);
2130 cop->l = CEND;
2131
2132 custom.cop1lc = (u_short *)ZTWO_PADDR(copdisplay.init);
2133 custom.copjmp1 = 0;
2134}
2135
2136static void ami_reinit_copper(const struct amifb_par *par)
2137{
2138 copdisplay.init[cip_bplcon0].w[1] = ~(BPC0_BPU3 | BPC0_BPU2 | BPC0_BPU1 | BPC0_BPU0) & par->bplcon0;
2139 copdisplay.wait->l = CWAIT(32, par->diwstrt_v - 4);
2140}
2141
2142
2143 /*
2144 * Rebuild the Copper List
2145 *
2146 * We only change the things that are not static
2147 */
2148
2149static void ami_rebuild_copper(const struct amifb_par *par)
2150{
2151 copins *copl, *cops;
2152 u_short line, h_end1, h_end2;
2153 short i;
2154 u_long p;
2155
2156 if (IS_AGA && maxfmode + par->clk_shift == 0)
2157 h_end1 = par->diwstrt_h - 64;
2158 else
2159 h_end1 = par->htotal - 32;
2160 h_end2 = par->ddfstop + 64;
2161
2162 ami_set_sprite(par);
2163
2164 copl = copdisplay.rebuild[1];
2165 p = par->bplpt0;
2166 if (par->vmode & FB_VMODE_YWRAP) {
2167 if ((par->vyres - par->yoffset) != 1 || !mod2(par->diwstrt_v)) {
2168 if (par->yoffset > par->vyres - par->yres) {
2169 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
2170 (copl++)->l = CMOVE(highw(p), bplpt[i]);
2171 (copl++)->l = CMOVE2(loww(p), bplpt[i]);
2172 }
2173 line = par->diwstrt_v + ((par->vyres - par->yoffset) << par->line_shift) - 1;
2174 while (line >= 512) {
2175 (copl++)->l = CWAIT(h_end1, 510);
2176 line -= 512;
2177 }
2178 if (line >= 510 && IS_AGA && maxfmode + par->clk_shift == 0)
2179 (copl++)->l = CWAIT(h_end1, line);
2180 else
2181 (copl++)->l = CWAIT(h_end2, line);
2182 p = par->bplpt0wrap;
2183 }
2184 } else
2185 p = par->bplpt0wrap;
2186 }
2187 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
2188 (copl++)->l = CMOVE(highw(p), bplpt[i]);
2189 (copl++)->l = CMOVE2(loww(p), bplpt[i]);
2190 }
2191 copl->l = CEND;
2192
2193 if (par->bplcon0 & BPC0_LACE) {
2194 cops = copdisplay.rebuild[0];
2195 p = par->bplpt0;
2196 if (mod2(par->diwstrt_v))
2197 p -= par->next_line;
2198 else
2199 p += par->next_line;
2200 if (par->vmode & FB_VMODE_YWRAP) {
2201 if ((par->vyres - par->yoffset) != 1 || mod2(par->diwstrt_v)) {
2202 if (par->yoffset > par->vyres - par->yres + 1) {
2203 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
2204 (cops++)->l = CMOVE(highw(p), bplpt[i]);
2205 (cops++)->l = CMOVE2(loww(p), bplpt[i]);
2206 }
2207 line = par->diwstrt_v + ((par->vyres - par->yoffset) << par->line_shift) - 2;
2208 while (line >= 512) {
2209 (cops++)->l = CWAIT(h_end1, 510);
2210 line -= 512;
2211 }
2212 if (line > 510 && IS_AGA && maxfmode + par->clk_shift == 0)
2213 (cops++)->l = CWAIT(h_end1, line);
2214 else
2215 (cops++)->l = CWAIT(h_end2, line);
2216 p = par->bplpt0wrap;
2217 if (mod2(par->diwstrt_v + par->vyres -
2218 par->yoffset))
2219 p -= par->next_line;
2220 else
2221 p += par->next_line;
2222 }
2223 } else
2224 p = par->bplpt0wrap - par->next_line;
2225 }
2226 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
2227 (cops++)->l = CMOVE(highw(p), bplpt[i]);
2228 (cops++)->l = CMOVE2(loww(p), bplpt[i]);
2229 }
2230 cops->l = CEND;
2231 }
2232}
2233
2234
2235 /*
2236 * Build the Copper List
2237 */
2238
2239static void ami_build_copper(struct fb_info *info)
2240{
2241 struct amifb_par *par = info->par;
2242 copins *copl, *cops;
2243 u_long p;
2244
2245 currentcop = 1 - currentcop;
2246
2247 copl = copdisplay.list[currentcop][1];
2248
2249 (copl++)->l = CWAIT(0, 10);
2250 (copl++)->l = CMOVE(par->bplcon0, bplcon0);
2251 (copl++)->l = CMOVE(0, sprpt[0]);
2252 (copl++)->l = CMOVE2(0, sprpt[0]);
2253
2254 if (par->bplcon0 & BPC0_LACE) {
2255 cops = copdisplay.list[currentcop][0];
2256
2257 (cops++)->l = CWAIT(0, 10);
2258 (cops++)->l = CMOVE(par->bplcon0, bplcon0);
2259 (cops++)->l = CMOVE(0, sprpt[0]);
2260 (cops++)->l = CMOVE2(0, sprpt[0]);
2261
2262 (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v + 1), diwstrt);
2263 (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v + 1), diwstop);
2264 (cops++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
2265 (cops++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
2266 if (!IS_OCS) {
2267 (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v + 1,
2268 par->diwstop_h, par->diwstop_v + 1), diwhigh);
2269 (cops++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
2270 par->diwstop_h, par->diwstop_v), diwhigh);
2271#if 0
2272 if (par->beamcon0 & BMC0_VARBEAMEN) {
2273 (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
2274 (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt + 1), vbstrt);
2275 (copl++)->l = CMOVE(vbstop2hw(par->vbstop + 1), vbstop);
2276 (cops++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
2277 (cops++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
2278 (cops++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
2279 }
2280#endif
2281 }
2282 p = ZTWO_PADDR(copdisplay.list[currentcop][0]);
2283 (copl++)->l = CMOVE(highw(p), cop2lc);
2284 (copl++)->l = CMOVE2(loww(p), cop2lc);
2285 p = ZTWO_PADDR(copdisplay.list[currentcop][1]);
2286 (cops++)->l = CMOVE(highw(p), cop2lc);
2287 (cops++)->l = CMOVE2(loww(p), cop2lc);
2288 copdisplay.rebuild[0] = cops;
2289 } else {
2290 (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
2291 (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
2292 if (!IS_OCS) {
2293 (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
2294 par->diwstop_h, par->diwstop_v), diwhigh);
2295#if 0
2296 if (par->beamcon0 & BMC0_VARBEAMEN) {
2297 (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
2298 (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
2299 (copl++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
2300 }
2301#endif
2302 }
2303 }
2304 copdisplay.rebuild[1] = copl;
2305
2306 ami_update_par(info);
2307 ami_rebuild_copper(info->par);
2308}
1174 2309
1175static struct fb_ops amifb_ops = {
1176 .owner = THIS_MODULE,
1177 .fb_check_var = amifb_check_var,
1178 .fb_set_par = amifb_set_par,
1179 .fb_setcolreg = amifb_setcolreg,
1180 .fb_blank = amifb_blank,
1181 .fb_pan_display = amifb_pan_display,
1182 .fb_fillrect = amifb_fillrect,
1183 .fb_copyarea = amifb_copyarea,
1184 .fb_imageblit = amifb_imageblit,
1185 .fb_ioctl = amifb_ioctl,
1186};
1187 2310
1188static void __init amifb_setup_mcap(char *spec) 2311static void __init amifb_setup_mcap(char *spec)
1189{ 2312{
@@ -1216,13 +2339,13 @@ static void __init amifb_setup_mcap(char *spec)
1216 if (hmax <= 0 || hmax <= hmin) 2339 if (hmax <= 0 || hmax <= hmin)
1217 return; 2340 return;
1218 2341
1219 fb_info.monspecs.vfmin = vmin; 2342 amifb_hfmin = hmin;
1220 fb_info.monspecs.vfmax = vmax; 2343 amifb_hfmax = hmax;
1221 fb_info.monspecs.hfmin = hmin; 2344 amifb_vfmin = vmin;
1222 fb_info.monspecs.hfmax = hmax; 2345 amifb_vfmax = vmax;
1223} 2346}
1224 2347
1225int __init amifb_setup(char *options) 2348static int __init amifb_setup(char *options)
1226{ 2349{
1227 char *this_opt; 2350 char *this_opt;
1228 2351
@@ -1238,9 +2361,9 @@ int __init amifb_setup(char *options)
1238 } else if (!strcmp(this_opt, "ilbm")) 2361 } else if (!strcmp(this_opt, "ilbm"))
1239 amifb_ilbm = 1; 2362 amifb_ilbm = 1;
1240 else if (!strncmp(this_opt, "monitorcap:", 11)) 2363 else if (!strncmp(this_opt, "monitorcap:", 11))
1241 amifb_setup_mcap(this_opt+11); 2364 amifb_setup_mcap(this_opt + 11);
1242 else if (!strncmp(this_opt, "fstart:", 7)) 2365 else if (!strncmp(this_opt, "fstart:", 7))
1243 min_fstrt = simple_strtoul(this_opt+7, NULL, 0); 2366 min_fstrt = simple_strtoul(this_opt + 7, NULL, 0);
1244 else 2367 else
1245 mode_option = this_opt; 2368 mode_option = this_opt;
1246 } 2369 }
@@ -1259,7 +2382,8 @@ static int amifb_check_var(struct fb_var_screeninfo *var,
1259 struct amifb_par par; 2382 struct amifb_par par;
1260 2383
1261 /* Validate wanted screen parameters */ 2384 /* Validate wanted screen parameters */
1262 if ((err = ami_decode_var(var, &par))) 2385 err = ami_decode_var(var, &par, info);
2386 if (err)
1263 return err; 2387 return err;
1264 2388
1265 /* Encode (possibly rounded) screen parameters */ 2389 /* Encode (possibly rounded) screen parameters */
@@ -1270,16 +2394,19 @@ static int amifb_check_var(struct fb_var_screeninfo *var,
1270 2394
1271static int amifb_set_par(struct fb_info *info) 2395static int amifb_set_par(struct fb_info *info)
1272{ 2396{
1273 struct amifb_par *par = (struct amifb_par *)info->par; 2397 struct amifb_par *par = info->par;
2398 int error;
1274 2399
1275 do_vmode_pan = 0; 2400 do_vmode_pan = 0;
1276 do_vmode_full = 0; 2401 do_vmode_full = 0;
1277 2402
1278 /* Decode wanted screen parameters */ 2403 /* Decode wanted screen parameters */
1279 ami_decode_var(&info->var, par); 2404 error = ami_decode_var(&info->var, par, info);
2405 if (error)
2406 return error;
1280 2407
1281 /* Set new videomode */ 2408 /* Set new videomode */
1282 ami_build_copper(); 2409 ami_build_copper(info);
1283 2410
1284 /* Set VBlank trigger */ 2411 /* Set VBlank trigger */
1285 do_vmode_full = 1; 2412 do_vmode_full = 1;
@@ -1295,20 +2422,20 @@ static int amifb_set_par(struct fb_info *info)
1295 info->fix.type = FB_TYPE_PLANES; 2422 info->fix.type = FB_TYPE_PLANES;
1296 info->fix.type_aux = 0; 2423 info->fix.type_aux = 0;
1297 } 2424 }
1298 info->fix.line_length = div8(upx(16<<maxfmode, par->vxres)); 2425 info->fix.line_length = div8(upx(16 << maxfmode, par->vxres));
1299 2426
1300 if (par->vmode & FB_VMODE_YWRAP) { 2427 if (par->vmode & FB_VMODE_YWRAP) {
1301 info->fix.ywrapstep = 1; 2428 info->fix.ywrapstep = 1;
1302 info->fix.xpanstep = 0; 2429 info->fix.xpanstep = 0;
1303 info->fix.ypanstep = 0; 2430 info->fix.ypanstep = 0;
1304 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YWRAP | 2431 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YWRAP |
1305 FBINFO_READS_FAST; /* override SCROLL_REDRAW */ 2432 FBINFO_READS_FAST; /* override SCROLL_REDRAW */
1306 } else { 2433 } else {
1307 info->fix.ywrapstep = 0; 2434 info->fix.ywrapstep = 0;
1308 if (par->vmode & FB_VMODE_SMOOTH_XPAN) 2435 if (par->vmode & FB_VMODE_SMOOTH_XPAN)
1309 info->fix.xpanstep = 1; 2436 info->fix.xpanstep = 1;
1310 else 2437 else
1311 info->fix.xpanstep = 16<<maxfmode; 2438 info->fix.xpanstep = 16 << maxfmode;
1312 info->fix.ypanstep = 1; 2439 info->fix.ypanstep = 1;
1313 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; 2440 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
1314 } 2441 }
@@ -1317,6 +2444,95 @@ static int amifb_set_par(struct fb_info *info)
1317 2444
1318 2445
1319 /* 2446 /*
2447 * Set a single color register. The values supplied are already
2448 * rounded down to the hardware's capabilities (according to the
2449 * entries in the var structure). Return != 0 for invalid regno.
2450 */
2451
2452static int amifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
2453 u_int transp, struct fb_info *info)
2454{
2455 const struct amifb_par *par = info->par;
2456
2457 if (IS_AGA) {
2458 if (regno > 255)
2459 return 1;
2460 } else if (par->bplcon0 & BPC0_SHRES) {
2461 if (regno > 3)
2462 return 1;
2463 } else {
2464 if (regno > 31)
2465 return 1;
2466 }
2467 red >>= 8;
2468 green >>= 8;
2469 blue >>= 8;
2470 if (!regno) {
2471 red0 = red;
2472 green0 = green;
2473 blue0 = blue;
2474 }
2475
2476 /*
2477 * Update the corresponding Hardware Color Register, unless it's Color
2478 * Register 0 and the screen is blanked.
2479 *
2480 * VBlank is switched off to protect bplcon3 or ecs_palette[] from
2481 * being changed by ami_do_blank() during the VBlank.
2482 */
2483
2484 if (regno || !is_blanked) {
2485#if defined(CONFIG_FB_AMIGA_AGA)
2486 if (IS_AGA) {
2487 u_short bplcon3 = par->bplcon3;
2488 VBlankOff();
2489 custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000);
2490 custom.color[regno & 31] = rgb2hw8_high(red, green,
2491 blue);
2492 custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000) |
2493 BPC3_LOCT;
2494 custom.color[regno & 31] = rgb2hw8_low(red, green,
2495 blue);
2496 custom.bplcon3 = bplcon3;
2497 VBlankOn();
2498 } else
2499#endif
2500#if defined(CONFIG_FB_AMIGA_ECS)
2501 if (par->bplcon0 & BPC0_SHRES) {
2502 u_short color, mask;
2503 int i;
2504
2505 mask = 0x3333;
2506 color = rgb2hw2(red, green, blue);
2507 VBlankOff();
2508 for (i = regno + 12; i >= (int)regno; i -= 4)
2509 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
2510 mask <<= 2; color >>= 2;
2511 regno = down16(regno) + mul4(mod4(regno));
2512 for (i = regno + 3; i >= (int)regno; i--)
2513 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
2514 VBlankOn();
2515 } else
2516#endif
2517 custom.color[regno] = rgb2hw4(red, green, blue);
2518 }
2519 return 0;
2520}
2521
2522
2523 /*
2524 * Blank the display.
2525 */
2526
2527static int amifb_blank(int blank, struct fb_info *info)
2528{
2529 do_blank = blank ? blank : -1;
2530
2531 return 0;
2532}
2533
2534
2535 /*
1320 * Pan or Wrap the Display 2536 * Pan or Wrap the Display
1321 * 2537 *
1322 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag 2538 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
@@ -1327,18 +2543,19 @@ static int amifb_pan_display(struct fb_var_screeninfo *var,
1327{ 2543{
1328 if (var->vmode & FB_VMODE_YWRAP) { 2544 if (var->vmode & FB_VMODE_YWRAP) {
1329 if (var->yoffset < 0 || 2545 if (var->yoffset < 0 ||
1330 var->yoffset >= info->var.yres_virtual || var->xoffset) 2546 var->yoffset >= info->var.yres_virtual || var->xoffset)
1331 return -EINVAL; 2547 return -EINVAL;
1332 } else { 2548 } else {
1333 /* 2549 /*
1334 * TODO: There will be problems when xpan!=1, so some columns 2550 * TODO: There will be problems when xpan!=1, so some columns
1335 * on the right side will never be seen 2551 * on the right side will never be seen
1336 */ 2552 */
1337 if (var->xoffset+info->var.xres > upx(16<<maxfmode, info->var.xres_virtual) || 2553 if (var->xoffset + info->var.xres >
1338 var->yoffset+info->var.yres > info->var.yres_virtual) 2554 upx(16 << maxfmode, info->var.xres_virtual) ||
2555 var->yoffset + info->var.yres > info->var.yres_virtual)
1339 return -EINVAL; 2556 return -EINVAL;
1340 } 2557 }
1341 ami_pan_var(var); 2558 ami_pan_var(var, info);
1342 info->var.xoffset = var->xoffset; 2559 info->var.xoffset = var->xoffset;
1343 info->var.yoffset = var->yoffset; 2560 info->var.yoffset = var->yoffset;
1344 if (var->vmode & FB_VMODE_YWRAP) 2561 if (var->vmode & FB_VMODE_YWRAP)
@@ -1360,10 +2577,10 @@ static int amifb_pan_display(struct fb_var_screeninfo *var,
1360#endif 2577#endif
1361 2578
1362 2579
1363 /* 2580 /*
1364 * Compose two values, using a bitmask as decision value 2581 * Compose two values, using a bitmask as decision value
1365 * This is equivalent to (a & mask) | (b & ~mask) 2582 * This is equivalent to (a & mask) | (b & ~mask)
1366 */ 2583 */
1367 2584
1368static inline unsigned long comp(unsigned long a, unsigned long b, 2585static inline unsigned long comp(unsigned long a, unsigned long b,
1369 unsigned long mask) 2586 unsigned long mask)
@@ -1379,29 +2596,29 @@ static inline unsigned long xor(unsigned long a, unsigned long b,
1379} 2596}
1380 2597
1381 2598
1382 /* 2599 /*
1383 * Unaligned forward bit copy using 32-bit or 64-bit memory accesses 2600 * Unaligned forward bit copy using 32-bit or 64-bit memory accesses
1384 */ 2601 */
1385 2602
1386static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src, 2603static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
1387 int src_idx, u32 n) 2604 int src_idx, u32 n)
1388{ 2605{
1389 unsigned long first, last; 2606 unsigned long first, last;
1390 int shift = dst_idx-src_idx, left, right; 2607 int shift = dst_idx - src_idx, left, right;
1391 unsigned long d0, d1; 2608 unsigned long d0, d1;
1392 int m; 2609 int m;
1393 2610
1394 if (!n) 2611 if (!n)
1395 return; 2612 return;
1396 2613
1397 shift = dst_idx-src_idx; 2614 shift = dst_idx - src_idx;
1398 first = ~0UL >> dst_idx; 2615 first = ~0UL >> dst_idx;
1399 last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG)); 2616 last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
1400 2617
1401 if (!shift) { 2618 if (!shift) {
1402 // Same alignment for source and dest 2619 // Same alignment for source and dest
1403 2620
1404 if (dst_idx+n <= BITS_PER_LONG) { 2621 if (dst_idx + n <= BITS_PER_LONG) {
1405 // Single word 2622 // Single word
1406 if (last) 2623 if (last)
1407 first &= last; 2624 first &= last;
@@ -1413,7 +2630,7 @@ static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
1413 *dst = comp(*src, *dst, first); 2630 *dst = comp(*src, *dst, first);
1414 dst++; 2631 dst++;
1415 src++; 2632 src++;
1416 n -= BITS_PER_LONG-dst_idx; 2633 n -= BITS_PER_LONG - dst_idx;
1417 } 2634 }
1418 2635
1419 // Main chunk 2636 // Main chunk
@@ -1439,17 +2656,17 @@ static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
1439 } else { 2656 } else {
1440 // Different alignment for source and dest 2657 // Different alignment for source and dest
1441 2658
1442 right = shift & (BITS_PER_LONG-1); 2659 right = shift & (BITS_PER_LONG - 1);
1443 left = -shift & (BITS_PER_LONG-1); 2660 left = -shift & (BITS_PER_LONG - 1);
1444 2661
1445 if (dst_idx+n <= BITS_PER_LONG) { 2662 if (dst_idx + n <= BITS_PER_LONG) {
1446 // Single destination word 2663 // Single destination word
1447 if (last) 2664 if (last)
1448 first &= last; 2665 first &= last;
1449 if (shift > 0) { 2666 if (shift > 0) {
1450 // Single source word 2667 // Single source word
1451 *dst = comp(*src >> right, *dst, first); 2668 *dst = comp(*src >> right, *dst, first);
1452 } else if (src_idx+n <= BITS_PER_LONG) { 2669 } else if (src_idx + n <= BITS_PER_LONG) {
1453 // Single source word 2670 // Single source word
1454 *dst = comp(*src << left, *dst, first); 2671 *dst = comp(*src << left, *dst, first);
1455 } else { 2672 } else {
@@ -1467,7 +2684,7 @@ static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
1467 // Single source word 2684 // Single source word
1468 *dst = comp(d0 >> right, *dst, first); 2685 *dst = comp(d0 >> right, *dst, first);
1469 dst++; 2686 dst++;
1470 n -= BITS_PER_LONG-dst_idx; 2687 n -= BITS_PER_LONG - dst_idx;
1471 } else { 2688 } else {
1472 // 2 source words 2689 // 2 source words
1473 d1 = *src++; 2690 d1 = *src++;
@@ -1475,7 +2692,7 @@ static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
1475 first); 2692 first);
1476 d0 = d1; 2693 d0 = d1;
1477 dst++; 2694 dst++;
1478 n -= BITS_PER_LONG-dst_idx; 2695 n -= BITS_PER_LONG - dst_idx;
1479 } 2696 }
1480 2697
1481 // Main chunk 2698 // Main chunk
@@ -1519,40 +2736,40 @@ static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
1519} 2736}
1520 2737
1521 2738
1522 /* 2739 /*
1523 * Unaligned reverse bit copy using 32-bit or 64-bit memory accesses 2740 * Unaligned reverse bit copy using 32-bit or 64-bit memory accesses
1524 */ 2741 */
1525 2742
1526static void bitcpy_rev(unsigned long *dst, int dst_idx, 2743static void bitcpy_rev(unsigned long *dst, int dst_idx,
1527 const unsigned long *src, int src_idx, u32 n) 2744 const unsigned long *src, int src_idx, u32 n)
1528{ 2745{
1529 unsigned long first, last; 2746 unsigned long first, last;
1530 int shift = dst_idx-src_idx, left, right; 2747 int shift = dst_idx - src_idx, left, right;
1531 unsigned long d0, d1; 2748 unsigned long d0, d1;
1532 int m; 2749 int m;
1533 2750
1534 if (!n) 2751 if (!n)
1535 return; 2752 return;
1536 2753
1537 dst += (n-1)/BITS_PER_LONG; 2754 dst += (n - 1) / BITS_PER_LONG;
1538 src += (n-1)/BITS_PER_LONG; 2755 src += (n - 1) / BITS_PER_LONG;
1539 if ((n-1) % BITS_PER_LONG) { 2756 if ((n - 1) % BITS_PER_LONG) {
1540 dst_idx += (n-1) % BITS_PER_LONG; 2757 dst_idx += (n - 1) % BITS_PER_LONG;
1541 dst += dst_idx >> SHIFT_PER_LONG; 2758 dst += dst_idx >> SHIFT_PER_LONG;
1542 dst_idx &= BITS_PER_LONG-1; 2759 dst_idx &= BITS_PER_LONG - 1;
1543 src_idx += (n-1) % BITS_PER_LONG; 2760 src_idx += (n - 1) % BITS_PER_LONG;
1544 src += src_idx >> SHIFT_PER_LONG; 2761 src += src_idx >> SHIFT_PER_LONG;
1545 src_idx &= BITS_PER_LONG-1; 2762 src_idx &= BITS_PER_LONG - 1;
1546 } 2763 }
1547 2764
1548 shift = dst_idx-src_idx; 2765 shift = dst_idx - src_idx;
1549 first = ~0UL << (BITS_PER_LONG-1-dst_idx); 2766 first = ~0UL << (BITS_PER_LONG - 1 - dst_idx);
1550 last = ~(~0UL << (BITS_PER_LONG-1-((dst_idx-n) % BITS_PER_LONG))); 2767 last = ~(~0UL << (BITS_PER_LONG - 1 - ((dst_idx - n) % BITS_PER_LONG)));
1551 2768
1552 if (!shift) { 2769 if (!shift) {
1553 // Same alignment for source and dest 2770 // Same alignment for source and dest
1554 2771
1555 if ((unsigned long)dst_idx+1 >= n) { 2772 if ((unsigned long)dst_idx + 1 >= n) {
1556 // Single word 2773 // Single word
1557 if (last) 2774 if (last)
1558 first &= last; 2775 first &= last;
@@ -1564,7 +2781,7 @@ static void bitcpy_rev(unsigned long *dst, int dst_idx,
1564 *dst = comp(*src, *dst, first); 2781 *dst = comp(*src, *dst, first);
1565 dst--; 2782 dst--;
1566 src--; 2783 src--;
1567 n -= dst_idx+1; 2784 n -= dst_idx + 1;
1568 } 2785 }
1569 2786
1570 // Main chunk 2787 // Main chunk
@@ -1590,17 +2807,17 @@ static void bitcpy_rev(unsigned long *dst, int dst_idx,
1590 } else { 2807 } else {
1591 // Different alignment for source and dest 2808 // Different alignment for source and dest
1592 2809
1593 right = shift & (BITS_PER_LONG-1); 2810 right = shift & (BITS_PER_LONG - 1);
1594 left = -shift & (BITS_PER_LONG-1); 2811 left = -shift & (BITS_PER_LONG - 1);
1595 2812
1596 if ((unsigned long)dst_idx+1 >= n) { 2813 if ((unsigned long)dst_idx + 1 >= n) {
1597 // Single destination word 2814 // Single destination word
1598 if (last) 2815 if (last)
1599 first &= last; 2816 first &= last;
1600 if (shift < 0) { 2817 if (shift < 0) {
1601 // Single source word 2818 // Single source word
1602 *dst = comp(*src << left, *dst, first); 2819 *dst = comp(*src << left, *dst, first);
1603 } else if (1+(unsigned long)src_idx >= n) { 2820 } else if (1 + (unsigned long)src_idx >= n) {
1604 // Single source word 2821 // Single source word
1605 *dst = comp(*src >> right, *dst, first); 2822 *dst = comp(*src >> right, *dst, first);
1606 } else { 2823 } else {
@@ -1618,7 +2835,7 @@ static void bitcpy_rev(unsigned long *dst, int dst_idx,
1618 // Single source word 2835 // Single source word
1619 *dst = comp(d0 << left, *dst, first); 2836 *dst = comp(d0 << left, *dst, first);
1620 dst--; 2837 dst--;
1621 n -= dst_idx+1; 2838 n -= dst_idx + 1;
1622 } else { 2839 } else {
1623 // 2 source words 2840 // 2 source words
1624 d1 = *src--; 2841 d1 = *src--;
@@ -1626,7 +2843,7 @@ static void bitcpy_rev(unsigned long *dst, int dst_idx,
1626 first); 2843 first);
1627 d0 = d1; 2844 d0 = d1;
1628 dst--; 2845 dst--;
1629 n -= dst_idx+1; 2846 n -= dst_idx + 1;
1630 } 2847 }
1631 2848
1632 // Main chunk 2849 // Main chunk
@@ -1670,30 +2887,30 @@ static void bitcpy_rev(unsigned long *dst, int dst_idx,
1670} 2887}
1671 2888
1672 2889
1673 /* 2890 /*
1674 * Unaligned forward inverting bit copy using 32-bit or 64-bit memory 2891 * Unaligned forward inverting bit copy using 32-bit or 64-bit memory
1675 * accesses 2892 * accesses
1676 */ 2893 */
1677 2894
1678static void bitcpy_not(unsigned long *dst, int dst_idx, 2895static void bitcpy_not(unsigned long *dst, int dst_idx,
1679 const unsigned long *src, int src_idx, u32 n) 2896 const unsigned long *src, int src_idx, u32 n)
1680{ 2897{
1681 unsigned long first, last; 2898 unsigned long first, last;
1682 int shift = dst_idx-src_idx, left, right; 2899 int shift = dst_idx - src_idx, left, right;
1683 unsigned long d0, d1; 2900 unsigned long d0, d1;
1684 int m; 2901 int m;
1685 2902
1686 if (!n) 2903 if (!n)
1687 return; 2904 return;
1688 2905
1689 shift = dst_idx-src_idx; 2906 shift = dst_idx - src_idx;
1690 first = ~0UL >> dst_idx; 2907 first = ~0UL >> dst_idx;
1691 last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG)); 2908 last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
1692 2909
1693 if (!shift) { 2910 if (!shift) {
1694 // Same alignment for source and dest 2911 // Same alignment for source and dest
1695 2912
1696 if (dst_idx+n <= BITS_PER_LONG) { 2913 if (dst_idx + n <= BITS_PER_LONG) {
1697 // Single word 2914 // Single word
1698 if (last) 2915 if (last)
1699 first &= last; 2916 first &= last;
@@ -1705,7 +2922,7 @@ static void bitcpy_not(unsigned long *dst, int dst_idx,
1705 *dst = comp(~*src, *dst, first); 2922 *dst = comp(~*src, *dst, first);
1706 dst++; 2923 dst++;
1707 src++; 2924 src++;
1708 n -= BITS_PER_LONG-dst_idx; 2925 n -= BITS_PER_LONG - dst_idx;
1709 } 2926 }
1710 2927
1711 // Main chunk 2928 // Main chunk
@@ -1731,17 +2948,17 @@ static void bitcpy_not(unsigned long *dst, int dst_idx,
1731 } else { 2948 } else {
1732 // Different alignment for source and dest 2949 // Different alignment for source and dest
1733 2950
1734 right = shift & (BITS_PER_LONG-1); 2951 right = shift & (BITS_PER_LONG - 1);
1735 left = -shift & (BITS_PER_LONG-1); 2952 left = -shift & (BITS_PER_LONG - 1);
1736 2953
1737 if (dst_idx+n <= BITS_PER_LONG) { 2954 if (dst_idx + n <= BITS_PER_LONG) {
1738 // Single destination word 2955 // Single destination word
1739 if (last) 2956 if (last)
1740 first &= last; 2957 first &= last;
1741 if (shift > 0) { 2958 if (shift > 0) {
1742 // Single source word 2959 // Single source word
1743 *dst = comp(~*src >> right, *dst, first); 2960 *dst = comp(~*src >> right, *dst, first);
1744 } else if (src_idx+n <= BITS_PER_LONG) { 2961 } else if (src_idx + n <= BITS_PER_LONG) {
1745 // Single source word 2962 // Single source word
1746 *dst = comp(~*src << left, *dst, first); 2963 *dst = comp(~*src << left, *dst, first);
1747 } else { 2964 } else {
@@ -1759,7 +2976,7 @@ static void bitcpy_not(unsigned long *dst, int dst_idx,
1759 // Single source word 2976 // Single source word
1760 *dst = comp(d0 >> right, *dst, first); 2977 *dst = comp(d0 >> right, *dst, first);
1761 dst++; 2978 dst++;
1762 n -= BITS_PER_LONG-dst_idx; 2979 n -= BITS_PER_LONG - dst_idx;
1763 } else { 2980 } else {
1764 // 2 source words 2981 // 2 source words
1765 d1 = ~*src++; 2982 d1 = ~*src++;
@@ -1767,7 +2984,7 @@ static void bitcpy_not(unsigned long *dst, int dst_idx,
1767 first); 2984 first);
1768 d0 = d1; 2985 d0 = d1;
1769 dst++; 2986 dst++;
1770 n -= BITS_PER_LONG-dst_idx; 2987 n -= BITS_PER_LONG - dst_idx;
1771 } 2988 }
1772 2989
1773 // Main chunk 2990 // Main chunk
@@ -1811,9 +3028,9 @@ static void bitcpy_not(unsigned long *dst, int dst_idx,
1811} 3028}
1812 3029
1813 3030
1814 /* 3031 /*
1815 * Unaligned 32-bit pattern fill using 32/64-bit memory accesses 3032 * Unaligned 32-bit pattern fill using 32/64-bit memory accesses
1816 */ 3033 */
1817 3034
1818static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n) 3035static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
1819{ 3036{
@@ -1828,9 +3045,9 @@ static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
1828#endif 3045#endif
1829 3046
1830 first = ~0UL >> dst_idx; 3047 first = ~0UL >> dst_idx;
1831 last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG)); 3048 last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
1832 3049
1833 if (dst_idx+n <= BITS_PER_LONG) { 3050 if (dst_idx + n <= BITS_PER_LONG) {
1834 // Single word 3051 // Single word
1835 if (last) 3052 if (last)
1836 first &= last; 3053 first &= last;
@@ -1841,7 +3058,7 @@ static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
1841 if (first) { 3058 if (first) {
1842 *dst = comp(val, *dst, first); 3059 *dst = comp(val, *dst, first);
1843 dst++; 3060 dst++;
1844 n -= BITS_PER_LONG-dst_idx; 3061 n -= BITS_PER_LONG - dst_idx;
1845 } 3062 }
1846 3063
1847 // Main chunk 3064 // Main chunk
@@ -1867,9 +3084,9 @@ static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
1867} 3084}
1868 3085
1869 3086
1870 /* 3087 /*
1871 * Unaligned 32-bit pattern xor using 32/64-bit memory accesses 3088 * Unaligned 32-bit pattern xor using 32/64-bit memory accesses
1872 */ 3089 */
1873 3090
1874static void bitxor32(unsigned long *dst, int dst_idx, u32 pat, u32 n) 3091static void bitxor32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
1875{ 3092{
@@ -1884,9 +3101,9 @@ static void bitxor32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
1884#endif 3101#endif
1885 3102
1886 first = ~0UL >> dst_idx; 3103 first = ~0UL >> dst_idx;
1887 last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG)); 3104 last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
1888 3105
1889 if (dst_idx+n <= BITS_PER_LONG) { 3106 if (dst_idx + n <= BITS_PER_LONG) {
1890 // Single word 3107 // Single word
1891 if (last) 3108 if (last)
1892 first &= last; 3109 first &= last;
@@ -1897,7 +3114,7 @@ static void bitxor32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
1897 if (first) { 3114 if (first) {
1898 *dst = xor(val, *dst, first); 3115 *dst = xor(val, *dst, first);
1899 dst++; 3116 dst++;
1900 n -= BITS_PER_LONG-dst_idx; 3117 n -= BITS_PER_LONG - dst_idx;
1901 } 3118 }
1902 3119
1903 // Main chunk 3120 // Main chunk
@@ -1924,12 +3141,12 @@ static inline void fill_one_line(int bpp, unsigned long next_plane,
1924{ 3141{
1925 while (1) { 3142 while (1) {
1926 dst += dst_idx >> SHIFT_PER_LONG; 3143 dst += dst_idx >> SHIFT_PER_LONG;
1927 dst_idx &= (BITS_PER_LONG-1); 3144 dst_idx &= (BITS_PER_LONG - 1);
1928 bitfill32(dst, dst_idx, color & 1 ? ~0 : 0, n); 3145 bitfill32(dst, dst_idx, color & 1 ? ~0 : 0, n);
1929 if (!--bpp) 3146 if (!--bpp)
1930 break; 3147 break;
1931 color >>= 1; 3148 color >>= 1;
1932 dst_idx += next_plane*8; 3149 dst_idx += next_plane * 8;
1933 } 3150 }
1934} 3151}
1935 3152
@@ -1939,12 +3156,12 @@ static inline void xor_one_line(int bpp, unsigned long next_plane,
1939{ 3156{
1940 while (color) { 3157 while (color) {
1941 dst += dst_idx >> SHIFT_PER_LONG; 3158 dst += dst_idx >> SHIFT_PER_LONG;
1942 dst_idx &= (BITS_PER_LONG-1); 3159 dst_idx &= (BITS_PER_LONG - 1);
1943 bitxor32(dst, dst_idx, color & 1 ? ~0 : 0, n); 3160 bitxor32(dst, dst_idx, color & 1 ? ~0 : 0, n);
1944 if (!--bpp) 3161 if (!--bpp)
1945 break; 3162 break;
1946 color >>= 1; 3163 color >>= 1;
1947 dst_idx += next_plane*8; 3164 dst_idx += next_plane * 8;
1948 } 3165 }
1949} 3166}
1950 3167
@@ -1952,7 +3169,7 @@ static inline void xor_one_line(int bpp, unsigned long next_plane,
1952static void amifb_fillrect(struct fb_info *info, 3169static void amifb_fillrect(struct fb_info *info,
1953 const struct fb_fillrect *rect) 3170 const struct fb_fillrect *rect)
1954{ 3171{
1955 struct amifb_par *par = (struct amifb_par *)info->par; 3172 struct amifb_par *par = info->par;
1956 int dst_idx, x2, y2; 3173 int dst_idx, x2, y2;
1957 unsigned long *dst; 3174 unsigned long *dst;
1958 u32 width, height; 3175 u32 width, height;
@@ -1972,23 +3189,23 @@ static void amifb_fillrect(struct fb_info *info,
1972 height = y2 - rect->dy; 3189 height = y2 - rect->dy;
1973 3190
1974 dst = (unsigned long *) 3191 dst = (unsigned long *)
1975 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1)); 3192 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
1976 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8; 3193 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
1977 dst_idx += rect->dy*par->next_line*8+rect->dx; 3194 dst_idx += rect->dy * par->next_line * 8 + rect->dx;
1978 while (height--) { 3195 while (height--) {
1979 switch (rect->rop) { 3196 switch (rect->rop) {
1980 case ROP_COPY: 3197 case ROP_COPY:
1981 fill_one_line(info->var.bits_per_pixel, 3198 fill_one_line(info->var.bits_per_pixel,
1982 par->next_plane, dst, dst_idx, width, 3199 par->next_plane, dst, dst_idx, width,
1983 rect->color); 3200 rect->color);
1984 break; 3201 break;
1985 3202
1986 case ROP_XOR: 3203 case ROP_XOR:
1987 xor_one_line(info->var.bits_per_pixel, par->next_plane, 3204 xor_one_line(info->var.bits_per_pixel, par->next_plane,
1988 dst, dst_idx, width, rect->color); 3205 dst, dst_idx, width, rect->color);
1989 break; 3206 break;
1990 } 3207 }
1991 dst_idx += par->next_line*8; 3208 dst_idx += par->next_line * 8;
1992 } 3209 }
1993} 3210}
1994 3211
@@ -1998,14 +3215,14 @@ static inline void copy_one_line(int bpp, unsigned long next_plane,
1998{ 3215{
1999 while (1) { 3216 while (1) {
2000 dst += dst_idx >> SHIFT_PER_LONG; 3217 dst += dst_idx >> SHIFT_PER_LONG;
2001 dst_idx &= (BITS_PER_LONG-1); 3218 dst_idx &= (BITS_PER_LONG - 1);
2002 src += src_idx >> SHIFT_PER_LONG; 3219 src += src_idx >> SHIFT_PER_LONG;
2003 src_idx &= (BITS_PER_LONG-1); 3220 src_idx &= (BITS_PER_LONG - 1);
2004 bitcpy(dst, dst_idx, src, src_idx, n); 3221 bitcpy(dst, dst_idx, src, src_idx, n);
2005 if (!--bpp) 3222 if (!--bpp)
2006 break; 3223 break;
2007 dst_idx += next_plane*8; 3224 dst_idx += next_plane * 8;
2008 src_idx += next_plane*8; 3225 src_idx += next_plane * 8;
2009 } 3226 }
2010} 3227}
2011 3228
@@ -2015,14 +3232,14 @@ static inline void copy_one_line_rev(int bpp, unsigned long next_plane,
2015{ 3232{
2016 while (1) { 3233 while (1) {
2017 dst += dst_idx >> SHIFT_PER_LONG; 3234 dst += dst_idx >> SHIFT_PER_LONG;
2018 dst_idx &= (BITS_PER_LONG-1); 3235 dst_idx &= (BITS_PER_LONG - 1);
2019 src += src_idx >> SHIFT_PER_LONG; 3236 src += src_idx >> SHIFT_PER_LONG;
2020 src_idx &= (BITS_PER_LONG-1); 3237 src_idx &= (BITS_PER_LONG - 1);
2021 bitcpy_rev(dst, dst_idx, src, src_idx, n); 3238 bitcpy_rev(dst, dst_idx, src, src_idx, n);
2022 if (!--bpp) 3239 if (!--bpp)
2023 break; 3240 break;
2024 dst_idx += next_plane*8; 3241 dst_idx += next_plane * 8;
2025 src_idx += next_plane*8; 3242 src_idx += next_plane * 8;
2026 } 3243 }
2027} 3244}
2028 3245
@@ -2030,7 +3247,7 @@ static inline void copy_one_line_rev(int bpp, unsigned long next_plane,
2030static void amifb_copyarea(struct fb_info *info, 3247static void amifb_copyarea(struct fb_info *info,
2031 const struct fb_copyarea *area) 3248 const struct fb_copyarea *area)
2032{ 3249{
2033 struct amifb_par *par = (struct amifb_par *)info->par; 3250 struct amifb_par *par = info->par;
2034 int x2, y2; 3251 int x2, y2;
2035 u32 dx, dy, sx, sy, width, height; 3252 u32 dx, dy, sx, sy, width, height;
2036 unsigned long *dst, *src; 3253 unsigned long *dst, *src;
@@ -2065,16 +3282,16 @@ static void amifb_copyarea(struct fb_info *info,
2065 rev_copy = 1; 3282 rev_copy = 1;
2066 } 3283 }
2067 dst = (unsigned long *) 3284 dst = (unsigned long *)
2068 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1)); 3285 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
2069 src = dst; 3286 src = dst;
2070 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8; 3287 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
2071 src_idx = dst_idx; 3288 src_idx = dst_idx;
2072 dst_idx += dy*par->next_line*8+dx; 3289 dst_idx += dy * par->next_line * 8 + dx;
2073 src_idx += sy*par->next_line*8+sx; 3290 src_idx += sy * par->next_line * 8 + sx;
2074 if (rev_copy) { 3291 if (rev_copy) {
2075 while (height--) { 3292 while (height--) {
2076 dst_idx -= par->next_line*8; 3293 dst_idx -= par->next_line * 8;
2077 src_idx -= par->next_line*8; 3294 src_idx -= par->next_line * 8;
2078 copy_one_line_rev(info->var.bits_per_pixel, 3295 copy_one_line_rev(info->var.bits_per_pixel,
2079 par->next_plane, dst, dst_idx, src, 3296 par->next_plane, dst, dst_idx, src,
2080 src_idx, width); 3297 src_idx, width);
@@ -2084,8 +3301,8 @@ static void amifb_copyarea(struct fb_info *info,
2084 copy_one_line(info->var.bits_per_pixel, 3301 copy_one_line(info->var.bits_per_pixel,
2085 par->next_plane, dst, dst_idx, src, 3302 par->next_plane, dst, dst_idx, src,
2086 src_idx, width); 3303 src_idx, width);
2087 dst_idx += par->next_line*8; 3304 dst_idx += par->next_line * 8;
2088 src_idx += par->next_line*8; 3305 src_idx += par->next_line * 8;
2089 } 3306 }
2090 } 3307 }
2091} 3308}
@@ -2095,34 +3312,35 @@ static inline void expand_one_line(int bpp, unsigned long next_plane,
2095 unsigned long *dst, int dst_idx, u32 n, 3312 unsigned long *dst, int dst_idx, u32 n,
2096 const u8 *data, u32 bgcolor, u32 fgcolor) 3313 const u8 *data, u32 bgcolor, u32 fgcolor)
2097{ 3314{
2098 const unsigned long *src; 3315 const unsigned long *src;
2099 int src_idx; 3316 int src_idx;
2100 3317
2101 while (1) { 3318 while (1) {
2102 dst += dst_idx >> SHIFT_PER_LONG; 3319 dst += dst_idx >> SHIFT_PER_LONG;
2103 dst_idx &= (BITS_PER_LONG-1); 3320 dst_idx &= (BITS_PER_LONG - 1);
2104 if ((bgcolor ^ fgcolor) & 1) { 3321 if ((bgcolor ^ fgcolor) & 1) {
2105 src = (unsigned long *)((unsigned long)data & ~(BYTES_PER_LONG-1)); 3322 src = (unsigned long *)
2106 src_idx = ((unsigned long)data & (BYTES_PER_LONG-1))*8; 3323 ((unsigned long)data & ~(BYTES_PER_LONG - 1));
2107 if (fgcolor & 1) 3324 src_idx = ((unsigned long)data & (BYTES_PER_LONG - 1)) * 8;
2108 bitcpy(dst, dst_idx, src, src_idx, n); 3325 if (fgcolor & 1)
2109 else 3326 bitcpy(dst, dst_idx, src, src_idx, n);
2110 bitcpy_not(dst, dst_idx, src, src_idx, n); 3327 else
2111 /* set or clear */ 3328 bitcpy_not(dst, dst_idx, src, src_idx, n);
2112 } else 3329 /* set or clear */
2113 bitfill32(dst, dst_idx, fgcolor & 1 ? ~0 : 0, n); 3330 } else
2114 if (!--bpp) 3331 bitfill32(dst, dst_idx, fgcolor & 1 ? ~0 : 0, n);
2115 break; 3332 if (!--bpp)
2116 bgcolor >>= 1; 3333 break;
2117 fgcolor >>= 1; 3334 bgcolor >>= 1;
2118 dst_idx += next_plane*8; 3335 fgcolor >>= 1;
2119 } 3336 dst_idx += next_plane * 8;
3337 }
2120} 3338}
2121 3339
2122 3340
2123static void amifb_imageblit(struct fb_info *info, const struct fb_image *image) 3341static void amifb_imageblit(struct fb_info *info, const struct fb_image *image)
2124{ 3342{
2125 struct amifb_par *par = (struct amifb_par *)info->par; 3343 struct amifb_par *par = info->par;
2126 int x2, y2; 3344 int x2, y2;
2127 unsigned long *dst; 3345 unsigned long *dst;
2128 int dst_idx; 3346 int dst_idx;
@@ -2145,17 +3363,17 @@ static void amifb_imageblit(struct fb_info *info, const struct fb_image *image)
2145 3363
2146 if (image->depth == 1) { 3364 if (image->depth == 1) {
2147 dst = (unsigned long *) 3365 dst = (unsigned long *)
2148 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1)); 3366 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
2149 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8; 3367 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
2150 dst_idx += dy*par->next_line*8+dx; 3368 dst_idx += dy * par->next_line * 8 + dx;
2151 src = image->data; 3369 src = image->data;
2152 pitch = (image->width+7)/8; 3370 pitch = (image->width + 7) / 8;
2153 while (height--) { 3371 while (height--) {
2154 expand_one_line(info->var.bits_per_pixel, 3372 expand_one_line(info->var.bits_per_pixel,
2155 par->next_plane, dst, dst_idx, width, 3373 par->next_plane, dst, dst_idx, width,
2156 src, image->bg_color, 3374 src, image->bg_color,
2157 image->fg_color); 3375 image->fg_color);
2158 dst_idx += par->next_line*8; 3376 dst_idx += par->next_line * 8;
2159 src += pitch; 3377 src += pitch;
2160 } 3378 }
2161 } else { 3379 } else {
@@ -2182,45 +3400,119 @@ static int amifb_ioctl(struct fb_info *info,
2182 int i; 3400 int i;
2183 3401
2184 switch (cmd) { 3402 switch (cmd) {
2185 case FBIOGET_FCURSORINFO: 3403 case FBIOGET_FCURSORINFO:
2186 i = ami_get_fix_cursorinfo(&crsr.fix); 3404 i = ami_get_fix_cursorinfo(&crsr.fix, info->par);
2187 if (i) 3405 if (i)
2188 return i; 3406 return i;
2189 return copy_to_user(argp, &crsr.fix, 3407 return copy_to_user(argp, &crsr.fix,
2190 sizeof(crsr.fix)) ? -EFAULT : 0; 3408 sizeof(crsr.fix)) ? -EFAULT : 0;
2191 3409
2192 case FBIOGET_VCURSORINFO: 3410 case FBIOGET_VCURSORINFO:
2193 i = ami_get_var_cursorinfo(&crsr.var, 3411 i = ami_get_var_cursorinfo(&crsr.var,
2194 ((struct fb_var_cursorinfo __user *)arg)->data); 3412 ((struct fb_var_cursorinfo __user *)arg)->data,
2195 if (i) 3413 info->par);
2196 return i; 3414 if (i)
2197 return copy_to_user(argp, &crsr.var, 3415 return i;
2198 sizeof(crsr.var)) ? -EFAULT : 0; 3416 return copy_to_user(argp, &crsr.var,
2199 3417 sizeof(crsr.var)) ? -EFAULT : 0;
2200 case FBIOPUT_VCURSORINFO: 3418
2201 if (copy_from_user(&crsr.var, argp, sizeof(crsr.var))) 3419 case FBIOPUT_VCURSORINFO:
2202 return -EFAULT; 3420 if (copy_from_user(&crsr.var, argp, sizeof(crsr.var)))
2203 return ami_set_var_cursorinfo(&crsr.var, 3421 return -EFAULT;
2204 ((struct fb_var_cursorinfo __user *)arg)->data); 3422 return ami_set_var_cursorinfo(&crsr.var,
2205 3423 ((struct fb_var_cursorinfo __user *)arg)->data,
2206 case FBIOGET_CURSORSTATE: 3424 info->par);
2207 i = ami_get_cursorstate(&crsr.state); 3425
2208 if (i) 3426 case FBIOGET_CURSORSTATE:
2209 return i; 3427 i = ami_get_cursorstate(&crsr.state, info->par);
2210 return copy_to_user(argp, &crsr.state, 3428 if (i)
2211 sizeof(crsr.state)) ? -EFAULT : 0; 3429 return i;
2212 3430 return copy_to_user(argp, &crsr.state,
2213 case FBIOPUT_CURSORSTATE: 3431 sizeof(crsr.state)) ? -EFAULT : 0;
2214 if (copy_from_user(&crsr.state, argp, 3432
2215 sizeof(crsr.state))) 3433 case FBIOPUT_CURSORSTATE:
2216 return -EFAULT; 3434 if (copy_from_user(&crsr.state, argp, sizeof(crsr.state)))
2217 return ami_set_cursorstate(&crsr.state); 3435 return -EFAULT;
3436 return ami_set_cursorstate(&crsr.state, info->par);
2218 } 3437 }
2219 return -EINVAL; 3438 return -EINVAL;
2220} 3439}
2221 3440
2222 3441
2223 /* 3442 /*
3443 * Flash the cursor (called by VBlank interrupt)
3444 */
3445
3446static int flash_cursor(void)
3447{
3448 static int cursorcount = 1;
3449
3450 if (cursormode == FB_CURSOR_FLASH) {
3451 if (!--cursorcount) {
3452 cursorstate = -cursorstate;
3453 cursorcount = cursorrate;
3454 if (!is_blanked)
3455 return 1;
3456 }
3457 }
3458 return 0;
3459}
3460
3461 /*
3462 * VBlank Display Interrupt
3463 */
3464
3465static irqreturn_t amifb_interrupt(int irq, void *dev_id)
3466{
3467 struct amifb_par *par = dev_id;
3468
3469 if (do_vmode_pan || do_vmode_full)
3470 ami_update_display(par);
3471
3472 if (do_vmode_full)
3473 ami_init_display(par);
3474
3475 if (do_vmode_pan) {
3476 flash_cursor();
3477 ami_rebuild_copper(par);
3478 do_cursor = do_vmode_pan = 0;
3479 } else if (do_cursor) {
3480 flash_cursor();
3481 ami_set_sprite(par);
3482 do_cursor = 0;
3483 } else {
3484 if (flash_cursor())
3485 ami_set_sprite(par);
3486 }
3487
3488 if (do_blank) {
3489 ami_do_blank(par);
3490 do_blank = 0;
3491 }
3492
3493 if (do_vmode_full) {
3494 ami_reinit_copper(par);
3495 do_vmode_full = 0;
3496 }
3497 return IRQ_HANDLED;
3498}
3499
3500
3501static struct fb_ops amifb_ops = {
3502 .owner = THIS_MODULE,
3503 .fb_check_var = amifb_check_var,
3504 .fb_set_par = amifb_set_par,
3505 .fb_setcolreg = amifb_setcolreg,
3506 .fb_blank = amifb_blank,
3507 .fb_pan_display = amifb_pan_display,
3508 .fb_fillrect = amifb_fillrect,
3509 .fb_copyarea = amifb_copyarea,
3510 .fb_imageblit = amifb_imageblit,
3511 .fb_ioctl = amifb_ioctl,
3512};
3513
3514
3515 /*
2224 * Allocate, Clear and Align a Block of Chip Memory 3516 * Allocate, Clear and Align a Block of Chip Memory
2225 */ 3517 */
2226 3518
@@ -2250,6 +3542,7 @@ static inline void chipfree(void)
2250 3542
2251static int __init amifb_probe(struct platform_device *pdev) 3543static int __init amifb_probe(struct platform_device *pdev)
2252{ 3544{
3545 struct fb_info *info;
2253 int tag, i, err = 0; 3546 int tag, i, err = 0;
2254 u_long chipptr; 3547 u_long chipptr;
2255 u_int defmode; 3548 u_int defmode;
@@ -2265,71 +3558,80 @@ static int __init amifb_probe(struct platform_device *pdev)
2265#endif 3558#endif
2266 custom.dmacon = DMAF_ALL | DMAF_MASTER; 3559 custom.dmacon = DMAF_ALL | DMAF_MASTER;
2267 3560
3561 info = framebuffer_alloc(sizeof(struct amifb_par), &pdev->dev);
3562 if (!info) {
3563 dev_err(&pdev->dev, "framebuffer_alloc failed\n");
3564 return -ENOMEM;
3565 }
3566
3567 strcpy(info->fix.id, "Amiga ");
3568 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
3569 info->fix.accel = FB_ACCEL_AMIGABLITT;
3570
2268 switch (amiga_chipset) { 3571 switch (amiga_chipset) {
2269#ifdef CONFIG_FB_AMIGA_OCS 3572#ifdef CONFIG_FB_AMIGA_OCS
2270 case CS_OCS: 3573 case CS_OCS:
2271 strcat(fb_info.fix.id, "OCS"); 3574 strcat(info->fix.id, "OCS");
2272default_chipset: 3575default_chipset:
2273 chipset = TAG_OCS; 3576 chipset = TAG_OCS;
2274 maxdepth[TAG_SHRES] = 0; /* OCS means no SHRES */ 3577 maxdepth[TAG_SHRES] = 0; /* OCS means no SHRES */
2275 maxdepth[TAG_HIRES] = 4; 3578 maxdepth[TAG_HIRES] = 4;
2276 maxdepth[TAG_LORES] = 6; 3579 maxdepth[TAG_LORES] = 6;
2277 maxfmode = TAG_FMODE_1; 3580 maxfmode = TAG_FMODE_1;
2278 defmode = amiga_vblank == 50 ? DEFMODE_PAL 3581 defmode = amiga_vblank == 50 ? DEFMODE_PAL : DEFMODE_NTSC;
2279 : DEFMODE_NTSC; 3582 info->fix.smem_len = VIDEOMEMSIZE_OCS;
2280 fb_info.fix.smem_len = VIDEOMEMSIZE_OCS; 3583 break;
2281 break;
2282#endif /* CONFIG_FB_AMIGA_OCS */ 3584#endif /* CONFIG_FB_AMIGA_OCS */
2283 3585
2284#ifdef CONFIG_FB_AMIGA_ECS 3586#ifdef CONFIG_FB_AMIGA_ECS
2285 case CS_ECS: 3587 case CS_ECS:
2286 strcat(fb_info.fix.id, "ECS"); 3588 strcat(info->fix.id, "ECS");
2287 chipset = TAG_ECS; 3589 chipset = TAG_ECS;
2288 maxdepth[TAG_SHRES] = 2; 3590 maxdepth[TAG_SHRES] = 2;
2289 maxdepth[TAG_HIRES] = 4; 3591 maxdepth[TAG_HIRES] = 4;
2290 maxdepth[TAG_LORES] = 6; 3592 maxdepth[TAG_LORES] = 6;
2291 maxfmode = TAG_FMODE_1; 3593 maxfmode = TAG_FMODE_1;
2292 if (AMIGAHW_PRESENT(AMBER_FF)) 3594 if (AMIGAHW_PRESENT(AMBER_FF))
2293 defmode = amiga_vblank == 50 ? DEFMODE_AMBER_PAL 3595 defmode = amiga_vblank == 50 ? DEFMODE_AMBER_PAL
2294 : DEFMODE_AMBER_NTSC; 3596 : DEFMODE_AMBER_NTSC;
2295 else 3597 else
2296 defmode = amiga_vblank == 50 ? DEFMODE_PAL 3598 defmode = amiga_vblank == 50 ? DEFMODE_PAL
2297 : DEFMODE_NTSC; 3599 : DEFMODE_NTSC;
2298 if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT > 3600 if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT >
2299 VIDEOMEMSIZE_ECS_2M) 3601 VIDEOMEMSIZE_ECS_2M)
2300 fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_2M; 3602 info->fix.smem_len = VIDEOMEMSIZE_ECS_2M;
2301 else 3603 else
2302 fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_1M; 3604 info->fix.smem_len = VIDEOMEMSIZE_ECS_1M;
2303 break; 3605 break;
2304#endif /* CONFIG_FB_AMIGA_ECS */ 3606#endif /* CONFIG_FB_AMIGA_ECS */
2305 3607
2306#ifdef CONFIG_FB_AMIGA_AGA 3608#ifdef CONFIG_FB_AMIGA_AGA
2307 case CS_AGA: 3609 case CS_AGA:
2308 strcat(fb_info.fix.id, "AGA"); 3610 strcat(info->fix.id, "AGA");
2309 chipset = TAG_AGA; 3611 chipset = TAG_AGA;
2310 maxdepth[TAG_SHRES] = 8; 3612 maxdepth[TAG_SHRES] = 8;
2311 maxdepth[TAG_HIRES] = 8; 3613 maxdepth[TAG_HIRES] = 8;
2312 maxdepth[TAG_LORES] = 8; 3614 maxdepth[TAG_LORES] = 8;
2313 maxfmode = TAG_FMODE_4; 3615 maxfmode = TAG_FMODE_4;
2314 defmode = DEFMODE_AGA; 3616 defmode = DEFMODE_AGA;
2315 if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT > 3617 if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT >
2316 VIDEOMEMSIZE_AGA_2M) 3618 VIDEOMEMSIZE_AGA_2M)
2317 fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_2M; 3619 info->fix.smem_len = VIDEOMEMSIZE_AGA_2M;
2318 else 3620 else
2319 fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_1M; 3621 info->fix.smem_len = VIDEOMEMSIZE_AGA_1M;
2320 break; 3622 break;
2321#endif /* CONFIG_FB_AMIGA_AGA */ 3623#endif /* CONFIG_FB_AMIGA_AGA */
2322 3624
2323 default: 3625 default:
2324#ifdef CONFIG_FB_AMIGA_OCS 3626#ifdef CONFIG_FB_AMIGA_OCS
2325 printk("Unknown graphics chipset, defaulting to OCS\n"); 3627 printk("Unknown graphics chipset, defaulting to OCS\n");
2326 strcat(fb_info.fix.id, "Unknown"); 3628 strcat(info->fix.id, "Unknown");
2327 goto default_chipset; 3629 goto default_chipset;
2328#else /* CONFIG_FB_AMIGA_OCS */ 3630#else /* CONFIG_FB_AMIGA_OCS */
2329 err = -ENODEV; 3631 err = -ENODEV;
2330 goto amifb_error; 3632 goto release;
2331#endif /* CONFIG_FB_AMIGA_OCS */ 3633#endif /* CONFIG_FB_AMIGA_OCS */
2332 break; 3634 break;
2333 } 3635 }
2334 3636
2335 /* 3637 /*
@@ -2356,42 +3658,44 @@ default_chipset:
2356 } 3658 }
2357 } 3659 }
2358 3660
2359 /* 3661 if (amifb_hfmin) {
2360 * These monitor specs are for a typical Amiga monitor (e.g. A1960) 3662 info->monspecs.hfmin = amifb_hfmin;
2361 */ 3663 info->monspecs.hfmax = amifb_hfmax;
2362 if (fb_info.monspecs.hfmin == 0) { 3664 info->monspecs.vfmin = amifb_vfmin;
2363 fb_info.monspecs.hfmin = 15000; 3665 info->monspecs.vfmax = amifb_vfmax;
2364 fb_info.monspecs.hfmax = 38000; 3666 } else {
2365 fb_info.monspecs.vfmin = 49; 3667 /*
2366 fb_info.monspecs.vfmax = 90; 3668 * These are for a typical Amiga monitor (e.g. A1960)
3669 */
3670 info->monspecs.hfmin = 15000;
3671 info->monspecs.hfmax = 38000;
3672 info->monspecs.vfmin = 49;
3673 info->monspecs.vfmax = 90;
2367 } 3674 }
2368 3675
2369 fb_info.fbops = &amifb_ops; 3676 info->fbops = &amifb_ops;
2370 fb_info.par = &currentpar; 3677 info->flags = FBINFO_DEFAULT;
2371 fb_info.flags = FBINFO_DEFAULT; 3678 info->device = &pdev->dev;
2372 fb_info.device = &pdev->dev;
2373 3679
2374 if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb, 3680 if (!fb_find_mode(&info->var, info, mode_option, ami_modedb,
2375 NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) { 3681 NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) {
2376 err = -EINVAL; 3682 err = -EINVAL;
2377 goto amifb_error; 3683 goto release;
2378 } 3684 }
2379 3685
2380 fb_videomode_to_modelist(ami_modedb, NUM_TOTAL_MODES, 3686 fb_videomode_to_modelist(ami_modedb, NUM_TOTAL_MODES,
2381 &fb_info.modelist); 3687 &info->modelist);
2382 3688
2383 round_down_bpp = 0; 3689 round_down_bpp = 0;
2384 chipptr = chipalloc(fb_info.fix.smem_len+ 3690 chipptr = chipalloc(info->fix.smem_len + SPRITEMEMSIZE +
2385 SPRITEMEMSIZE+ 3691 DUMMYSPRITEMEMSIZE + COPINITSIZE +
2386 DUMMYSPRITEMEMSIZE+ 3692 4 * COPLISTSIZE);
2387 COPINITSIZE+
2388 4*COPLISTSIZE);
2389 if (!chipptr) { 3693 if (!chipptr) {
2390 err = -ENOMEM; 3694 err = -ENOMEM;
2391 goto amifb_error; 3695 goto release;
2392 } 3696 }
2393 3697
2394 assignchunk(videomemory, u_long, chipptr, fb_info.fix.smem_len); 3698 assignchunk(videomemory, u_long, chipptr, info->fix.smem_len);
2395 assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE); 3699 assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE);
2396 assignchunk(dummysprite, u_short *, chipptr, DUMMYSPRITEMEMSIZE); 3700 assignchunk(dummysprite, u_short *, chipptr, DUMMYSPRITEMEMSIZE);
2397 assignchunk(copdisplay.init, copins *, chipptr, COPINITSIZE); 3701 assignchunk(copdisplay.init, copins *, chipptr, COPINITSIZE);
@@ -2403,1398 +3707,78 @@ default_chipset:
2403 /* 3707 /*
2404 * access the videomem with writethrough cache 3708 * access the videomem with writethrough cache
2405 */ 3709 */
2406 fb_info.fix.smem_start = (u_long)ZTWO_PADDR(videomemory); 3710 info->fix.smem_start = (u_long)ZTWO_PADDR(videomemory);
2407 videomemory = (u_long)ioremap_writethrough(fb_info.fix.smem_start, 3711 videomemory = (u_long)ioremap_writethrough(info->fix.smem_start,
2408 fb_info.fix.smem_len); 3712 info->fix.smem_len);
2409 if (!videomemory) { 3713 if (!videomemory) {
2410 printk("amifb: WARNING! unable to map videomem cached writethrough\n"); 3714 dev_warn(&pdev->dev,
2411 fb_info.screen_base = (char *)ZTWO_VADDR(fb_info.fix.smem_start); 3715 "Unable to map videomem cached writethrough\n");
3716 info->screen_base = (char *)ZTWO_VADDR(info->fix.smem_start);
2412 } else 3717 } else
2413 fb_info.screen_base = (char *)videomemory; 3718 info->screen_base = (char *)videomemory;
2414 3719
2415 memset(dummysprite, 0, DUMMYSPRITEMEMSIZE); 3720 memset(dummysprite, 0, DUMMYSPRITEMEMSIZE);
2416 3721
2417 /* 3722 /*
2418 * Enable Display DMA
2419 */
2420
2421 custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
2422 DMAF_BLITTER | DMAF_SPRITE;
2423
2424 /*
2425 * Make sure the Copper has something to do 3723 * Make sure the Copper has something to do
2426 */ 3724 */
2427
2428 ami_init_copper(); 3725 ami_init_copper();
2429 3726
2430 if (request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, 0,
2431 "fb vertb handler", &currentpar)) {
2432 err = -EBUSY;
2433 goto amifb_error;
2434 }
2435
2436 err = fb_alloc_cmap(&fb_info.cmap, 1<<fb_info.var.bits_per_pixel, 0);
2437 if (err)
2438 goto amifb_error;
2439
2440 if (register_framebuffer(&fb_info) < 0) {
2441 err = -EINVAL;
2442 goto amifb_error;
2443 }
2444
2445 printk("fb%d: %s frame buffer device, using %dK of video memory\n",
2446 fb_info.node, fb_info.fix.id, fb_info.fix.smem_len>>10);
2447
2448 return 0;
2449
2450amifb_error:
2451 amifb_deinit(pdev);
2452 return err;
2453}
2454
2455static void amifb_deinit(struct platform_device *pdev)
2456{
2457 if (fb_info.cmap.len)
2458 fb_dealloc_cmap(&fb_info.cmap);
2459 fb_dealloc_cmap(&fb_info.cmap);
2460 chipfree();
2461 if (videomemory)
2462 iounmap((void*)videomemory);
2463 custom.dmacon = DMAF_ALL | DMAF_MASTER;
2464}
2465
2466
2467 /*
2468 * Blank the display.
2469 */
2470
2471static int amifb_blank(int blank, struct fb_info *info)
2472{
2473 do_blank = blank ? blank : -1;
2474
2475 return 0;
2476}
2477
2478 /*
2479 * Flash the cursor (called by VBlank interrupt)
2480 */
2481
2482static int flash_cursor(void)
2483{
2484 static int cursorcount = 1;
2485
2486 if (cursormode == FB_CURSOR_FLASH) {
2487 if (!--cursorcount) {
2488 cursorstate = -cursorstate;
2489 cursorcount = cursorrate;
2490 if (!is_blanked)
2491 return 1;
2492 }
2493 }
2494 return 0;
2495}
2496
2497 /*
2498 * VBlank Display Interrupt
2499 */
2500
2501static irqreturn_t amifb_interrupt(int irq, void *dev_id)
2502{
2503 if (do_vmode_pan || do_vmode_full)
2504 ami_update_display();
2505
2506 if (do_vmode_full)
2507 ami_init_display();
2508
2509 if (do_vmode_pan) {
2510 flash_cursor();
2511 ami_rebuild_copper();
2512 do_cursor = do_vmode_pan = 0;
2513 } else if (do_cursor) {
2514 flash_cursor();
2515 ami_set_sprite();
2516 do_cursor = 0;
2517 } else {
2518 if (flash_cursor())
2519 ami_set_sprite();
2520 }
2521
2522 if (do_blank) {
2523 ami_do_blank();
2524 do_blank = 0;
2525 }
2526
2527 if (do_vmode_full) {
2528 ami_reinit_copper();
2529 do_vmode_full = 0;
2530 }
2531 return IRQ_HANDLED;
2532}
2533
2534/* --------------------------- Hardware routines --------------------------- */
2535
2536 /*
2537 * Get the video params out of `var'. If a value doesn't fit, round
2538 * it up, if it's too big, return -EINVAL.
2539 */
2540
2541static int ami_decode_var(struct fb_var_screeninfo *var,
2542 struct amifb_par *par)
2543{
2544 u_short clk_shift, line_shift;
2545 u_long maxfetchstop, fstrt, fsize, fconst, xres_n, yres_n;
2546 u_int htotal, vtotal;
2547
2548 /*
2549 * Find a matching Pixel Clock
2550 */
2551
2552 for (clk_shift = TAG_SHRES; clk_shift <= TAG_LORES; clk_shift++)
2553 if (var->pixclock <= pixclock[clk_shift])
2554 break;
2555 if (clk_shift > TAG_LORES) {
2556 DPRINTK("pixclock too high\n");
2557 return -EINVAL;
2558 }
2559 par->clk_shift = clk_shift;
2560
2561 /*
2562 * Check the Geometry Values
2563 */
2564
2565 if ((par->xres = var->xres) < 64)
2566 par->xres = 64;
2567 if ((par->yres = var->yres) < 64)
2568 par->yres = 64;
2569 if ((par->vxres = var->xres_virtual) < par->xres)
2570 par->vxres = par->xres;
2571 if ((par->vyres = var->yres_virtual) < par->yres)
2572 par->vyres = par->yres;
2573
2574 par->bpp = var->bits_per_pixel;
2575 if (!var->nonstd) {
2576 if (par->bpp < 1)
2577 par->bpp = 1;
2578 if (par->bpp > maxdepth[clk_shift]) {
2579 if (round_down_bpp && maxdepth[clk_shift])
2580 par->bpp = maxdepth[clk_shift];
2581 else {
2582 DPRINTK("invalid bpp\n");
2583 return -EINVAL;
2584 }
2585 }
2586 } else if (var->nonstd == FB_NONSTD_HAM) {
2587 if (par->bpp < 6)
2588 par->bpp = 6;
2589 if (par->bpp != 6) {
2590 if (par->bpp < 8)
2591 par->bpp = 8;
2592 if (par->bpp != 8 || !IS_AGA) {
2593 DPRINTK("invalid bpp for ham mode\n");
2594 return -EINVAL;
2595 }
2596 }
2597 } else {
2598 DPRINTK("unknown nonstd mode\n");
2599 return -EINVAL;
2600 }
2601
2602 /*
2603 * FB_VMODE_SMOOTH_XPAN will be cleared, if one of the folloing
2604 * checks failed and smooth scrolling is not possible
2605 */
2606
2607 par->vmode = var->vmode | FB_VMODE_SMOOTH_XPAN;
2608 switch (par->vmode & FB_VMODE_MASK) {
2609 case FB_VMODE_INTERLACED:
2610 line_shift = 0;
2611 break;
2612 case FB_VMODE_NONINTERLACED:
2613 line_shift = 1;
2614 break;
2615 case FB_VMODE_DOUBLE:
2616 if (!IS_AGA) {
2617 DPRINTK("double mode only possible with aga\n");
2618 return -EINVAL;
2619 }
2620 line_shift = 2;
2621 break;
2622 default:
2623 DPRINTK("unknown video mode\n");
2624 return -EINVAL;
2625 break;
2626 }
2627 par->line_shift = line_shift;
2628
2629 /*
2630 * Vertical and Horizontal Timings
2631 */
2632
2633 xres_n = par->xres<<clk_shift;
2634 yres_n = par->yres<<line_shift;
2635 par->htotal = down8((var->left_margin+par->xres+var->right_margin+var->hsync_len)<<clk_shift);
2636 par->vtotal = down2(((var->upper_margin+par->yres+var->lower_margin+var->vsync_len)<<line_shift)+1);
2637
2638 if (IS_AGA)
2639 par->bplcon3 = sprpixmode[clk_shift];
2640 else
2641 par->bplcon3 = 0;
2642 if (var->sync & FB_SYNC_BROADCAST) {
2643 par->diwstop_h = par->htotal-((var->right_margin-var->hsync_len)<<clk_shift);
2644 if (IS_AGA)
2645 par->diwstop_h += mod4(var->hsync_len);
2646 else
2647 par->diwstop_h = down4(par->diwstop_h);
2648
2649 par->diwstrt_h = par->diwstop_h - xres_n;
2650 par->diwstop_v = par->vtotal-((var->lower_margin-var->vsync_len)<<line_shift);
2651 par->diwstrt_v = par->diwstop_v - yres_n;
2652 if (par->diwstop_h >= par->htotal+8) {
2653 DPRINTK("invalid diwstop_h\n");
2654 return -EINVAL;
2655 }
2656 if (par->diwstop_v > par->vtotal) {
2657 DPRINTK("invalid diwstop_v\n");
2658 return -EINVAL;
2659 }
2660
2661 if (!IS_OCS) {
2662 /* Initialize sync with some reasonable values for pwrsave */
2663 par->hsstrt = 160;
2664 par->hsstop = 320;
2665 par->vsstrt = 30;
2666 par->vsstop = 34;
2667 } else {
2668 par->hsstrt = 0;
2669 par->hsstop = 0;
2670 par->vsstrt = 0;
2671 par->vsstop = 0;
2672 }
2673 if (par->vtotal > (PAL_VTOTAL+NTSC_VTOTAL)/2) {
2674 /* PAL video mode */
2675 if (par->htotal != PAL_HTOTAL) {
2676 DPRINTK("htotal invalid for pal\n");
2677 return -EINVAL;
2678 }
2679 if (par->diwstrt_h < PAL_DIWSTRT_H) {
2680 DPRINTK("diwstrt_h too low for pal\n");
2681 return -EINVAL;
2682 }
2683 if (par->diwstrt_v < PAL_DIWSTRT_V) {
2684 DPRINTK("diwstrt_v too low for pal\n");
2685 return -EINVAL;
2686 }
2687 htotal = PAL_HTOTAL>>clk_shift;
2688 vtotal = PAL_VTOTAL>>1;
2689 if (!IS_OCS) {
2690 par->beamcon0 = BMC0_PAL;
2691 par->bplcon3 |= BPC3_BRDRBLNK;
2692 } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
2693 AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
2694 par->beamcon0 = BMC0_PAL;
2695 par->hsstop = 1;
2696 } else if (amiga_vblank != 50) {
2697 DPRINTK("pal not supported by this chipset\n");
2698 return -EINVAL;
2699 }
2700 } else {
2701 /* NTSC video mode
2702 * In the AGA chipset seems to be hardware bug with BPC3_BRDRBLNK
2703 * and NTSC activated, so than better let diwstop_h <= 1812
2704 */
2705 if (par->htotal != NTSC_HTOTAL) {
2706 DPRINTK("htotal invalid for ntsc\n");
2707 return -EINVAL;
2708 }
2709 if (par->diwstrt_h < NTSC_DIWSTRT_H) {
2710 DPRINTK("diwstrt_h too low for ntsc\n");
2711 return -EINVAL;
2712 }
2713 if (par->diwstrt_v < NTSC_DIWSTRT_V) {
2714 DPRINTK("diwstrt_v too low for ntsc\n");
2715 return -EINVAL;
2716 }
2717 htotal = NTSC_HTOTAL>>clk_shift;
2718 vtotal = NTSC_VTOTAL>>1;
2719 if (!IS_OCS) {
2720 par->beamcon0 = 0;
2721 par->bplcon3 |= BPC3_BRDRBLNK;
2722 } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
2723 AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
2724 par->beamcon0 = 0;
2725 par->hsstop = 1;
2726 } else if (amiga_vblank != 60) {
2727 DPRINTK("ntsc not supported by this chipset\n");
2728 return -EINVAL;
2729 }
2730 }
2731 if (IS_OCS) {
2732 if (par->diwstrt_h >= 1024 || par->diwstop_h < 1024 ||
2733 par->diwstrt_v >= 512 || par->diwstop_v < 256) {
2734 DPRINTK("invalid position for display on ocs\n");
2735 return -EINVAL;
2736 }
2737 }
2738 } else if (!IS_OCS) {
2739 /* Programmable video mode */
2740 par->hsstrt = var->right_margin<<clk_shift;
2741 par->hsstop = (var->right_margin+var->hsync_len)<<clk_shift;
2742 par->diwstop_h = par->htotal - mod8(par->hsstrt) + 8 - (1 << clk_shift);
2743 if (!IS_AGA)
2744 par->diwstop_h = down4(par->diwstop_h) - 16;
2745 par->diwstrt_h = par->diwstop_h - xres_n;
2746 par->hbstop = par->diwstrt_h + 4;
2747 par->hbstrt = par->diwstop_h + 4;
2748 if (par->hbstrt >= par->htotal + 8)
2749 par->hbstrt -= par->htotal;
2750 par->hcenter = par->hsstrt + (par->htotal >> 1);
2751 par->vsstrt = var->lower_margin<<line_shift;
2752 par->vsstop = (var->lower_margin+var->vsync_len)<<line_shift;
2753 par->diwstop_v = par->vtotal;
2754 if ((par->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
2755 par->diwstop_v -= 2;
2756 par->diwstrt_v = par->diwstop_v - yres_n;
2757 par->vbstop = par->diwstrt_v - 2;
2758 par->vbstrt = par->diwstop_v - 2;
2759 if (par->vtotal > 2048) {
2760 DPRINTK("vtotal too high\n");
2761 return -EINVAL;
2762 }
2763 if (par->htotal > 2048) {
2764 DPRINTK("htotal too high\n");
2765 return -EINVAL;
2766 }
2767 par->bplcon3 |= BPC3_EXTBLKEN;
2768 par->beamcon0 = BMC0_HARDDIS | BMC0_VARVBEN | BMC0_LOLDIS |
2769 BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARBEAMEN |
2770 BMC0_PAL | BMC0_VARCSYEN;
2771 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
2772 par->beamcon0 |= BMC0_HSYTRUE;
2773 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
2774 par->beamcon0 |= BMC0_VSYTRUE;
2775 if (var->sync & FB_SYNC_COMP_HIGH_ACT)
2776 par->beamcon0 |= BMC0_CSYTRUE;
2777 htotal = par->htotal>>clk_shift;
2778 vtotal = par->vtotal>>1;
2779 } else {
2780 DPRINTK("only broadcast modes possible for ocs\n");
2781 return -EINVAL;
2782 }
2783
2784 /*
2785 * Checking the DMA timing
2786 */
2787
2788 fconst = 16<<maxfmode<<clk_shift;
2789
2790 /*
2791 * smallest window start value without turn off other dma cycles
2792 * than sprite1-7, unless you change min_fstrt
2793 */
2794
2795
2796 fsize = ((maxfmode+clk_shift <= 1) ? fconst : 64);
2797 fstrt = downx(fconst, par->diwstrt_h-4) - fsize;
2798 if (fstrt < min_fstrt) {
2799 DPRINTK("fetch start too low\n");
2800 return -EINVAL;
2801 }
2802
2803 /*
2804 * smallest window start value where smooth scrolling is possible
2805 */
2806
2807 fstrt = downx(fconst, par->diwstrt_h-fconst+(1<<clk_shift)-4) - fsize;
2808 if (fstrt < min_fstrt)
2809 par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
2810
2811 maxfetchstop = down16(par->htotal - 80);
2812
2813 fstrt = downx(fconst, par->diwstrt_h-4) - 64 - fconst;
2814 fsize = upx(fconst, xres_n + modx(fconst, downx(1<<clk_shift, par->diwstrt_h-4)));
2815 if (fstrt + fsize > maxfetchstop)
2816 par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
2817
2818 fsize = upx(fconst, xres_n);
2819 if (fstrt + fsize > maxfetchstop) {
2820 DPRINTK("fetch stop too high\n");
2821 return -EINVAL;
2822 }
2823
2824 if (maxfmode + clk_shift <= 1) {
2825 fsize = up64(xres_n + fconst - 1);
2826 if (min_fstrt + fsize - 64 > maxfetchstop)
2827 par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
2828
2829 fsize = up64(xres_n);
2830 if (min_fstrt + fsize - 64 > maxfetchstop) {
2831 DPRINTK("fetch size too high\n");
2832 return -EINVAL;
2833 }
2834
2835 fsize -= 64;
2836 } else
2837 fsize -= fconst;
2838
2839 /*
2840 * Check if there is enough time to update the bitplane pointers for ywrap
2841 */
2842
2843 if (par->htotal-fsize-64 < par->bpp*64)
2844 par->vmode &= ~FB_VMODE_YWRAP;
2845
2846 /*
2847 * Bitplane calculations and check the Memory Requirements
2848 */
2849
2850 if (amifb_ilbm) {
2851 par->next_plane = div8(upx(16<<maxfmode, par->vxres));
2852 par->next_line = par->bpp*par->next_plane;
2853 if (par->next_line * par->vyres > fb_info.fix.smem_len) {
2854 DPRINTK("too few video mem\n");
2855 return -EINVAL;
2856 }
2857 } else {
2858 par->next_line = div8(upx(16<<maxfmode, par->vxres));
2859 par->next_plane = par->vyres*par->next_line;
2860 if (par->next_plane * par->bpp > fb_info.fix.smem_len) {
2861 DPRINTK("too few video mem\n");
2862 return -EINVAL;
2863 }
2864 }
2865
2866 /*
2867 * Hardware Register Values
2868 */
2869
2870 par->bplcon0 = BPC0_COLOR | bplpixmode[clk_shift];
2871 if (!IS_OCS)
2872 par->bplcon0 |= BPC0_ECSENA;
2873 if (par->bpp == 8)
2874 par->bplcon0 |= BPC0_BPU3;
2875 else
2876 par->bplcon0 |= par->bpp<<12;
2877 if (var->nonstd == FB_NONSTD_HAM)
2878 par->bplcon0 |= BPC0_HAM;
2879 if (var->sync & FB_SYNC_EXT)
2880 par->bplcon0 |= BPC0_ERSY;
2881
2882 if (IS_AGA)
2883 par->fmode = bplfetchmode[maxfmode];
2884
2885 switch (par->vmode & FB_VMODE_MASK) {
2886 case FB_VMODE_INTERLACED:
2887 par->bplcon0 |= BPC0_LACE;
2888 break;
2889 case FB_VMODE_DOUBLE:
2890 if (IS_AGA)
2891 par->fmode |= FMODE_SSCAN2 | FMODE_BSCAN2;
2892 break;
2893 }
2894
2895 if (!((par->vmode ^ var->vmode) & FB_VMODE_YWRAP)) {
2896 par->xoffset = var->xoffset;
2897 par->yoffset = var->yoffset;
2898 if (par->vmode & FB_VMODE_YWRAP) {
2899 if (par->xoffset || par->yoffset < 0 || par->yoffset >= par->vyres)
2900 par->xoffset = par->yoffset = 0;
2901 } else {
2902 if (par->xoffset < 0 || par->xoffset > upx(16<<maxfmode, par->vxres-par->xres) ||
2903 par->yoffset < 0 || par->yoffset > par->vyres-par->yres)
2904 par->xoffset = par->yoffset = 0;
2905 }
2906 } else
2907 par->xoffset = par->yoffset = 0;
2908
2909 par->crsr.crsr_x = par->crsr.crsr_y = 0;
2910 par->crsr.spot_x = par->crsr.spot_y = 0;
2911 par->crsr.height = par->crsr.width = 0;
2912
2913 return 0;
2914}
2915
2916 /*
2917 * Fill the `var' structure based on the values in `par' and maybe
2918 * other values read out of the hardware.
2919 */
2920
2921static int ami_encode_var(struct fb_var_screeninfo *var,
2922 struct amifb_par *par)
2923{
2924 u_short clk_shift, line_shift;
2925
2926 memset(var, 0, sizeof(struct fb_var_screeninfo));
2927
2928 clk_shift = par->clk_shift;
2929 line_shift = par->line_shift;
2930
2931 var->xres = par->xres;
2932 var->yres = par->yres;
2933 var->xres_virtual = par->vxres;
2934 var->yres_virtual = par->vyres;
2935 var->xoffset = par->xoffset;
2936 var->yoffset = par->yoffset;
2937
2938 var->bits_per_pixel = par->bpp;
2939 var->grayscale = 0;
2940
2941 var->red.offset = 0;
2942 var->red.msb_right = 0;
2943 var->red.length = par->bpp;
2944 if (par->bplcon0 & BPC0_HAM)
2945 var->red.length -= 2;
2946 var->blue = var->green = var->red;
2947 var->transp.offset = 0;
2948 var->transp.length = 0;
2949 var->transp.msb_right = 0;
2950
2951 if (par->bplcon0 & BPC0_HAM)
2952 var->nonstd = FB_NONSTD_HAM;
2953 else
2954 var->nonstd = 0;
2955 var->activate = 0;
2956
2957 var->height = -1;
2958 var->width = -1;
2959
2960 var->pixclock = pixclock[clk_shift];
2961
2962 if (IS_AGA && par->fmode & FMODE_BSCAN2)
2963 var->vmode = FB_VMODE_DOUBLE;
2964 else if (par->bplcon0 & BPC0_LACE)
2965 var->vmode = FB_VMODE_INTERLACED;
2966 else
2967 var->vmode = FB_VMODE_NONINTERLACED;
2968
2969 if (!IS_OCS && par->beamcon0 & BMC0_VARBEAMEN) {
2970 var->hsync_len = (par->hsstop-par->hsstrt)>>clk_shift;
2971 var->right_margin = par->hsstrt>>clk_shift;
2972 var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
2973 var->vsync_len = (par->vsstop-par->vsstrt)>>line_shift;
2974 var->lower_margin = par->vsstrt>>line_shift;
2975 var->upper_margin = (par->vtotal>>line_shift) - var->yres - var->lower_margin - var->vsync_len;
2976 var->sync = 0;
2977 if (par->beamcon0 & BMC0_HSYTRUE)
2978 var->sync |= FB_SYNC_HOR_HIGH_ACT;
2979 if (par->beamcon0 & BMC0_VSYTRUE)
2980 var->sync |= FB_SYNC_VERT_HIGH_ACT;
2981 if (par->beamcon0 & BMC0_CSYTRUE)
2982 var->sync |= FB_SYNC_COMP_HIGH_ACT;
2983 } else {
2984 var->sync = FB_SYNC_BROADCAST;
2985 var->hsync_len = (152>>clk_shift) + mod4(par->diwstop_h);
2986 var->right_margin = ((par->htotal - down4(par->diwstop_h))>>clk_shift) + var->hsync_len;
2987 var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
2988 var->vsync_len = 4>>line_shift;
2989 var->lower_margin = ((par->vtotal - par->diwstop_v)>>line_shift) + var->vsync_len;
2990 var->upper_margin = (((par->vtotal - 2)>>line_shift) + 1) - var->yres -
2991 var->lower_margin - var->vsync_len;
2992 }
2993
2994 if (par->bplcon0 & BPC0_ERSY)
2995 var->sync |= FB_SYNC_EXT;
2996 if (par->vmode & FB_VMODE_YWRAP)
2997 var->vmode |= FB_VMODE_YWRAP;
2998
2999 return 0;
3000}
3001
3002
3003 /* 3727 /*
3004 * Pan or Wrap the Display 3728 * Enable Display DMA
3005 *
3006 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
3007 * in `var'.
3008 */
3009
3010static void ami_pan_var(struct fb_var_screeninfo *var)
3011{
3012 struct amifb_par *par = &currentpar;
3013
3014 par->xoffset = var->xoffset;
3015 par->yoffset = var->yoffset;
3016 if (var->vmode & FB_VMODE_YWRAP)
3017 par->vmode |= FB_VMODE_YWRAP;
3018 else
3019 par->vmode &= ~FB_VMODE_YWRAP;
3020
3021 do_vmode_pan = 0;
3022 ami_update_par();
3023 do_vmode_pan = 1;
3024}
3025
3026 /*
3027 * Update hardware
3028 */
3029
3030static int ami_update_par(void)
3031{
3032 struct amifb_par *par = &currentpar;
3033 short clk_shift, vshift, fstrt, fsize, fstop, fconst, shift, move, mod;
3034
3035 clk_shift = par->clk_shift;
3036
3037 if (!(par->vmode & FB_VMODE_SMOOTH_XPAN))
3038 par->xoffset = upx(16<<maxfmode, par->xoffset);
3039
3040 fconst = 16<<maxfmode<<clk_shift;
3041 vshift = modx(16<<maxfmode, par->xoffset);
3042 fstrt = par->diwstrt_h - (vshift<<clk_shift) - 4;
3043 fsize = (par->xres+vshift)<<clk_shift;
3044 shift = modx(fconst, fstrt);
3045 move = downx(2<<maxfmode, div8(par->xoffset));
3046 if (maxfmode + clk_shift > 1) {
3047 fstrt = downx(fconst, fstrt) - 64;
3048 fsize = upx(fconst, fsize);
3049 fstop = fstrt + fsize - fconst;
3050 } else {
3051 mod = fstrt = downx(fconst, fstrt) - fconst;
3052 fstop = fstrt + upx(fconst, fsize) - 64;
3053 fsize = up64(fsize);
3054 fstrt = fstop - fsize + 64;
3055 if (fstrt < min_fstrt) {
3056 fstop += min_fstrt - fstrt;
3057 fstrt = min_fstrt;
3058 }
3059 move = move - div8((mod-fstrt)>>clk_shift);
3060 }
3061 mod = par->next_line - div8(fsize>>clk_shift);
3062 par->ddfstrt = fstrt;
3063 par->ddfstop = fstop;
3064 par->bplcon1 = hscroll2hw(shift);
3065 par->bpl2mod = mod;
3066 if (par->bplcon0 & BPC0_LACE)
3067 par->bpl2mod += par->next_line;
3068 if (IS_AGA && (par->fmode & FMODE_BSCAN2))
3069 par->bpl1mod = -div8(fsize>>clk_shift);
3070 else
3071 par->bpl1mod = par->bpl2mod;
3072
3073 if (par->yoffset) {
3074 par->bplpt0 = fb_info.fix.smem_start + par->next_line*par->yoffset + move;
3075 if (par->vmode & FB_VMODE_YWRAP) {
3076 if (par->yoffset > par->vyres-par->yres) {
3077 par->bplpt0wrap = fb_info.fix.smem_start + move;
3078 if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v+par->vyres-par->yoffset))
3079 par->bplpt0wrap += par->next_line;
3080 }
3081 }
3082 } else
3083 par->bplpt0 = fb_info.fix.smem_start + move;
3084
3085 if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v))
3086 par->bplpt0 += par->next_line;
3087
3088 return 0;
3089}
3090
3091
3092 /*
3093 * Set a single color register. The values supplied are already
3094 * rounded down to the hardware's capabilities (according to the
3095 * entries in the var structure). Return != 0 for invalid regno.
3096 */
3097
3098static int amifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
3099 u_int transp, struct fb_info *info)
3100{
3101 if (IS_AGA) {
3102 if (regno > 255)
3103 return 1;
3104 } else if (currentpar.bplcon0 & BPC0_SHRES) {
3105 if (regno > 3)
3106 return 1;
3107 } else {
3108 if (regno > 31)
3109 return 1;
3110 }
3111 red >>= 8;
3112 green >>= 8;
3113 blue >>= 8;
3114 if (!regno) {
3115 red0 = red;
3116 green0 = green;
3117 blue0 = blue;
3118 }
3119
3120 /*
3121 * Update the corresponding Hardware Color Register, unless it's Color
3122 * Register 0 and the screen is blanked.
3123 *
3124 * VBlank is switched off to protect bplcon3 or ecs_palette[] from
3125 * being changed by ami_do_blank() during the VBlank.
3126 */
3127
3128 if (regno || !is_blanked) {
3129#if defined(CONFIG_FB_AMIGA_AGA)
3130 if (IS_AGA) {
3131 u_short bplcon3 = currentpar.bplcon3;
3132 VBlankOff();
3133 custom.bplcon3 = bplcon3 | (regno<<8 & 0xe000);
3134 custom.color[regno&31] = rgb2hw8_high(red, green, blue);
3135 custom.bplcon3 = bplcon3 | (regno<<8 & 0xe000) | BPC3_LOCT;
3136 custom.color[regno&31] = rgb2hw8_low(red, green, blue);
3137 custom.bplcon3 = bplcon3;
3138 VBlankOn();
3139 } else
3140#endif
3141#if defined(CONFIG_FB_AMIGA_ECS)
3142 if (currentpar.bplcon0 & BPC0_SHRES) {
3143 u_short color, mask;
3144 int i;
3145
3146 mask = 0x3333;
3147 color = rgb2hw2(red, green, blue);
3148 VBlankOff();
3149 for (i = regno+12; i >= (int)regno; i -= 4)
3150 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
3151 mask <<=2; color >>= 2;
3152 regno = down16(regno)+mul4(mod4(regno));
3153 for (i = regno+3; i >= (int)regno; i--)
3154 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
3155 VBlankOn();
3156 } else
3157#endif
3158 custom.color[regno] = rgb2hw4(red, green, blue);
3159 }
3160 return 0;
3161}
3162
3163static void ami_update_display(void)
3164{
3165 struct amifb_par *par = &currentpar;
3166
3167 custom.bplcon1 = par->bplcon1;
3168 custom.bpl1mod = par->bpl1mod;
3169 custom.bpl2mod = par->bpl2mod;
3170 custom.ddfstrt = ddfstrt2hw(par->ddfstrt);
3171 custom.ddfstop = ddfstop2hw(par->ddfstop);
3172}
3173
3174 /*
3175 * Change the video mode (called by VBlank interrupt)
3176 */
3177
3178static void ami_init_display(void)
3179{
3180 struct amifb_par *par = &currentpar;
3181 int i;
3182
3183 custom.bplcon0 = par->bplcon0 & ~BPC0_LACE;
3184 custom.bplcon2 = (IS_OCS ? 0 : BPC2_KILLEHB) | BPC2_PF2P2 | BPC2_PF1P2;
3185 if (!IS_OCS) {
3186 custom.bplcon3 = par->bplcon3;
3187 if (IS_AGA)
3188 custom.bplcon4 = BPC4_ESPRM4 | BPC4_OSPRM4;
3189 if (par->beamcon0 & BMC0_VARBEAMEN) {
3190 custom.htotal = htotal2hw(par->htotal);
3191 custom.hbstrt = hbstrt2hw(par->hbstrt);
3192 custom.hbstop = hbstop2hw(par->hbstop);
3193 custom.hsstrt = hsstrt2hw(par->hsstrt);
3194 custom.hsstop = hsstop2hw(par->hsstop);
3195 custom.hcenter = hcenter2hw(par->hcenter);
3196 custom.vtotal = vtotal2hw(par->vtotal);
3197 custom.vbstrt = vbstrt2hw(par->vbstrt);
3198 custom.vbstop = vbstop2hw(par->vbstop);
3199 custom.vsstrt = vsstrt2hw(par->vsstrt);
3200 custom.vsstop = vsstop2hw(par->vsstop);
3201 }
3202 }
3203 if (!IS_OCS || par->hsstop)
3204 custom.beamcon0 = par->beamcon0;
3205 if (IS_AGA)
3206 custom.fmode = par->fmode;
3207
3208 /*
3209 * The minimum period for audio depends on htotal
3210 */
3211
3212 amiga_audio_min_period = div16(par->htotal);
3213
3214 is_lace = par->bplcon0 & BPC0_LACE ? 1 : 0;
3215#if 1
3216 if (is_lace) {
3217 i = custom.vposr >> 15;
3218 } else {
3219 custom.vposw = custom.vposr | 0x8000;
3220 i = 1;
3221 }
3222#else
3223 i = 1;
3224 custom.vposw = custom.vposr | 0x8000;
3225#endif
3226 custom.cop2lc = (u_short *)ZTWO_PADDR(copdisplay.list[currentcop][i]);
3227}
3228
3229 /*
3230 * (Un)Blank the screen (called by VBlank interrupt)
3231 */ 3729 */
3730 custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
3731 DMAF_BLITTER | DMAF_SPRITE;
3232 3732
3233static void ami_do_blank(void) 3733 err = request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, 0,
3234{ 3734 "fb vertb handler", info->par);
3235 struct amifb_par *par = &currentpar; 3735 if (err)
3236#if defined(CONFIG_FB_AMIGA_AGA) 3736 goto disable_dma;
3237 u_short bplcon3 = par->bplcon3;
3238#endif
3239 u_char red, green, blue;
3240
3241 if (do_blank > 0) {
3242 custom.dmacon = DMAF_RASTER | DMAF_SPRITE;
3243 red = green = blue = 0;
3244 if (!IS_OCS && do_blank > 1) {
3245 switch (do_blank) {
3246 case FB_BLANK_VSYNC_SUSPEND:
3247 custom.hsstrt = hsstrt2hw(par->hsstrt);
3248 custom.hsstop = hsstop2hw(par->hsstop);
3249 custom.vsstrt = vsstrt2hw(par->vtotal+4);
3250 custom.vsstop = vsstop2hw(par->vtotal+4);
3251 break;
3252 case FB_BLANK_HSYNC_SUSPEND:
3253 custom.hsstrt = hsstrt2hw(par->htotal+16);
3254 custom.hsstop = hsstop2hw(par->htotal+16);
3255 custom.vsstrt = vsstrt2hw(par->vsstrt);
3256 custom.vsstop = vsstrt2hw(par->vsstop);
3257 break;
3258 case FB_BLANK_POWERDOWN:
3259 custom.hsstrt = hsstrt2hw(par->htotal+16);
3260 custom.hsstop = hsstop2hw(par->htotal+16);
3261 custom.vsstrt = vsstrt2hw(par->vtotal+4);
3262 custom.vsstop = vsstop2hw(par->vtotal+4);
3263 break;
3264 }
3265 if (!(par->beamcon0 & BMC0_VARBEAMEN)) {
3266 custom.htotal = htotal2hw(par->htotal);
3267 custom.vtotal = vtotal2hw(par->vtotal);
3268 custom.beamcon0 = BMC0_HARDDIS | BMC0_VARBEAMEN |
3269 BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARCSYEN;
3270 }
3271 }
3272 } else {
3273 custom.dmacon = DMAF_SETCLR | DMAF_RASTER | DMAF_SPRITE;
3274 red = red0;
3275 green = green0;
3276 blue = blue0;
3277 if (!IS_OCS) {
3278 custom.hsstrt = hsstrt2hw(par->hsstrt);
3279 custom.hsstop = hsstop2hw(par->hsstop);
3280 custom.vsstrt = vsstrt2hw(par->vsstrt);
3281 custom.vsstop = vsstop2hw(par->vsstop);
3282 custom.beamcon0 = par->beamcon0;
3283 }
3284 }
3285#if defined(CONFIG_FB_AMIGA_AGA)
3286 if (IS_AGA) {
3287 custom.bplcon3 = bplcon3;
3288 custom.color[0] = rgb2hw8_high(red, green, blue);
3289 custom.bplcon3 = bplcon3 | BPC3_LOCT;
3290 custom.color[0] = rgb2hw8_low(red, green, blue);
3291 custom.bplcon3 = bplcon3;
3292 } else
3293#endif
3294#if defined(CONFIG_FB_AMIGA_ECS)
3295 if (par->bplcon0 & BPC0_SHRES) {
3296 u_short color, mask;
3297 int i;
3298
3299 mask = 0x3333;
3300 color = rgb2hw2(red, green, blue);
3301 for (i = 12; i >= 0; i -= 4)
3302 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
3303 mask <<=2; color >>= 2;
3304 for (i = 3; i >= 0; i--)
3305 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
3306 } else
3307#endif
3308 custom.color[0] = rgb2hw4(red, green, blue);
3309 is_blanked = do_blank > 0 ? do_blank : 0;
3310}
3311
3312static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix)
3313{
3314 struct amifb_par *par = &currentpar;
3315
3316 fix->crsr_width = fix->crsr_xsize = par->crsr.width;
3317 fix->crsr_height = fix->crsr_ysize = par->crsr.height;
3318 fix->crsr_color1 = 17;
3319 fix->crsr_color2 = 18;
3320 return 0;
3321}
3322
3323static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data)
3324{
3325 struct amifb_par *par = &currentpar;
3326 register u_short *lspr, *sspr;
3327#ifdef __mc68000__
3328 register u_long datawords asm ("d2");
3329#else
3330 register u_long datawords;
3331#endif
3332 register short delta;
3333 register u_char color;
3334 short height, width, bits, words;
3335 int size, alloc;
3336
3337 size = par->crsr.height*par->crsr.width;
3338 alloc = var->height*var->width;
3339 var->height = par->crsr.height;
3340 var->width = par->crsr.width;
3341 var->xspot = par->crsr.spot_x;
3342 var->yspot = par->crsr.spot_y;
3343 if (size > var->height*var->width)
3344 return -ENAMETOOLONG;
3345 if (!access_ok(VERIFY_WRITE, data, size))
3346 return -EFAULT;
3347 delta = 1<<par->crsr.fmode;
3348 lspr = lofsprite + (delta<<1);
3349 if (par->bplcon0 & BPC0_LACE)
3350 sspr = shfsprite + (delta<<1);
3351 else
3352 sspr = NULL;
3353 for (height = (short)var->height-1; height >= 0; height--) {
3354 bits = 0; words = delta; datawords = 0;
3355 for (width = (short)var->width-1; width >= 0; width--) {
3356 if (bits == 0) {
3357 bits = 16; --words;
3358#ifdef __mc68000__
3359 asm volatile ("movew %1@(%3:w:2),%0 ; swap %0 ; movew %1@+,%0"
3360 : "=d" (datawords), "=a" (lspr) : "1" (lspr), "d" (delta));
3361#else
3362 datawords = (*(lspr+delta) << 16) | (*lspr++);
3363#endif
3364 }
3365 --bits;
3366#ifdef __mc68000__
3367 asm volatile (
3368 "clrb %0 ; swap %1 ; lslw #1,%1 ; roxlb #1,%0 ; "
3369 "swap %1 ; lslw #1,%1 ; roxlb #1,%0"
3370 : "=d" (color), "=d" (datawords) : "1" (datawords));
3371#else
3372 color = (((datawords >> 30) & 2)
3373 | ((datawords >> 15) & 1));
3374 datawords <<= 1;
3375#endif
3376 put_user(color, data++);
3377 }
3378 if (bits > 0) {
3379 --words; ++lspr;
3380 }
3381 while (--words >= 0)
3382 ++lspr;
3383#ifdef __mc68000__
3384 asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
3385 : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
3386#else
3387 lspr += delta;
3388 if (sspr) {
3389 u_short *tmp = lspr;
3390 lspr = sspr;
3391 sspr = tmp;
3392 }
3393#endif
3394 }
3395 return 0;
3396}
3397
3398static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data)
3399{
3400 struct amifb_par *par = &currentpar;
3401 register u_short *lspr, *sspr;
3402#ifdef __mc68000__
3403 register u_long datawords asm ("d2");
3404#else
3405 register u_long datawords;
3406#endif
3407 register short delta;
3408 u_short fmode;
3409 short height, width, bits, words;
3410 3737
3411 if (!var->width) 3738 err = fb_alloc_cmap(&info->cmap, 1 << info->var.bits_per_pixel, 0);
3412 return -EINVAL; 3739 if (err)
3413 else if (var->width <= 16) 3740 goto free_irq;
3414 fmode = TAG_FMODE_1;
3415 else if (var->width <= 32)
3416 fmode = TAG_FMODE_2;
3417 else if (var->width <= 64)
3418 fmode = TAG_FMODE_4;
3419 else
3420 return -EINVAL;
3421 if (fmode > maxfmode)
3422 return -EINVAL;
3423 if (!var->height)
3424 return -EINVAL;
3425 if (!access_ok(VERIFY_READ, data, var->width*var->height))
3426 return -EFAULT;
3427 delta = 1<<fmode;
3428 lofsprite = shfsprite = (u_short *)spritememory;
3429 lspr = lofsprite + (delta<<1);
3430 if (par->bplcon0 & BPC0_LACE) {
3431 if (((var->height+4)<<fmode<<2) > SPRITEMEMSIZE)
3432 return -EINVAL;
3433 memset(lspr, 0, (var->height+4)<<fmode<<2);
3434 shfsprite += ((var->height+5)&-2)<<fmode;
3435 sspr = shfsprite + (delta<<1);
3436 } else {
3437 if (((var->height+2)<<fmode<<2) > SPRITEMEMSIZE)
3438 return -EINVAL;
3439 memset(lspr, 0, (var->height+2)<<fmode<<2);
3440 sspr = NULL;
3441 }
3442 for (height = (short)var->height-1; height >= 0; height--) {
3443 bits = 16; words = delta; datawords = 0;
3444 for (width = (short)var->width-1; width >= 0; width--) {
3445 unsigned long tdata = 0;
3446 get_user(tdata, data);
3447 data++;
3448#ifdef __mc68000__
3449 asm volatile (
3450 "lsrb #1,%2 ; roxlw #1,%0 ; swap %0 ; "
3451 "lsrb #1,%2 ; roxlw #1,%0 ; swap %0"
3452 : "=d" (datawords)
3453 : "0" (datawords), "d" (tdata));
3454#else
3455 datawords = ((datawords << 1) & 0xfffefffe);
3456 datawords |= tdata & 1;
3457 datawords |= (tdata & 2) << (16-1);
3458#endif
3459 if (--bits == 0) {
3460 bits = 16; --words;
3461#ifdef __mc68000__
3462 asm volatile ("swap %2 ; movew %2,%0@(%3:w:2) ; swap %2 ; movew %2,%0@+"
3463 : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta));
3464#else
3465 *(lspr+delta) = (u_short) (datawords >> 16);
3466 *lspr++ = (u_short) (datawords & 0xffff);
3467#endif
3468 }
3469 }
3470 if (bits < 16) {
3471 --words;
3472#ifdef __mc68000__
3473 asm volatile (
3474 "swap %2 ; lslw %4,%2 ; movew %2,%0@(%3:w:2) ; "
3475 "swap %2 ; lslw %4,%2 ; movew %2,%0@+"
3476 : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta), "d" (bits));
3477#else
3478 *(lspr+delta) = (u_short) (datawords >> (16+bits));
3479 *lspr++ = (u_short) ((datawords & 0x0000ffff) >> bits);
3480#endif
3481 }
3482 while (--words >= 0) {
3483#ifdef __mc68000__
3484 asm volatile ("moveql #0,%%d0 ; movew %%d0,%0@(%2:w:2) ; movew %%d0,%0@+"
3485 : "=a" (lspr) : "0" (lspr), "d" (delta) : "d0");
3486#else
3487 *(lspr+delta) = 0;
3488 *lspr++ = 0;
3489#endif
3490 }
3491#ifdef __mc68000__
3492 asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
3493 : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
3494#else
3495 lspr += delta;
3496 if (sspr) {
3497 u_short *tmp = lspr;
3498 lspr = sspr;
3499 sspr = tmp;
3500 }
3501#endif
3502 }
3503 par->crsr.height = var->height;
3504 par->crsr.width = var->width;
3505 par->crsr.spot_x = var->xspot;
3506 par->crsr.spot_y = var->yspot;
3507 par->crsr.fmode = fmode;
3508 if (IS_AGA) {
3509 par->fmode &= ~(FMODE_SPAGEM | FMODE_SPR32);
3510 par->fmode |= sprfetchmode[fmode];
3511 custom.fmode = par->fmode;
3512 }
3513 return 0;
3514}
3515 3741
3516static int ami_get_cursorstate(struct fb_cursorstate *state) 3742 dev_set_drvdata(&pdev->dev, info);
3517{
3518 struct amifb_par *par = &currentpar;
3519 3743
3520 state->xoffset = par->crsr.crsr_x; 3744 err = register_framebuffer(info);
3521 state->yoffset = par->crsr.crsr_y; 3745 if (err)
3522 state->mode = cursormode; 3746 goto unset_drvdata;
3523 return 0;
3524}
3525 3747
3526static int ami_set_cursorstate(struct fb_cursorstate *state) 3748 printk("fb%d: %s frame buffer device, using %dK of video memory\n",
3527{ 3749 info->node, info->fix.id, info->fix.smem_len>>10);
3528 struct amifb_par *par = &currentpar;
3529 3750
3530 par->crsr.crsr_x = state->xoffset;
3531 par->crsr.crsr_y = state->yoffset;
3532 if ((cursormode = state->mode) == FB_CURSOR_OFF)
3533 cursorstate = -1;
3534 do_cursor = 1;
3535 return 0; 3751 return 0;
3536}
3537
3538static void ami_set_sprite(void)
3539{
3540 struct amifb_par *par = &currentpar;
3541 copins *copl, *cops;
3542 u_short hs, vs, ve;
3543 u_long pl, ps, pt;
3544 short mx, my;
3545
3546 cops = copdisplay.list[currentcop][0];
3547 copl = copdisplay.list[currentcop][1];
3548 ps = pl = ZTWO_PADDR(dummysprite);
3549 mx = par->crsr.crsr_x-par->crsr.spot_x;
3550 my = par->crsr.crsr_y-par->crsr.spot_y;
3551 if (!(par->vmode & FB_VMODE_YWRAP)) {
3552 mx -= par->xoffset;
3553 my -= par->yoffset;
3554 }
3555 if (!is_blanked && cursorstate > 0 && par->crsr.height > 0 &&
3556 mx > -(short)par->crsr.width && mx < par->xres &&
3557 my > -(short)par->crsr.height && my < par->yres) {
3558 pl = ZTWO_PADDR(lofsprite);
3559 hs = par->diwstrt_h + (mx<<par->clk_shift) - 4;
3560 vs = par->diwstrt_v + (my<<par->line_shift);
3561 ve = vs + (par->crsr.height<<par->line_shift);
3562 if (par->bplcon0 & BPC0_LACE) {
3563 ps = ZTWO_PADDR(shfsprite);
3564 lofsprite[0] = spr2hw_pos(vs, hs);
3565 shfsprite[0] = spr2hw_pos(vs+1, hs);
3566 if (mod2(vs)) {
3567 lofsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
3568 shfsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs+1, hs, ve+1);
3569 pt = pl; pl = ps; ps = pt;
3570 } else {
3571 lofsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs, hs, ve+1);
3572 shfsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs+1, hs, ve);
3573 }
3574 } else {
3575 lofsprite[0] = spr2hw_pos(vs, hs) | (IS_AGA && (par->fmode & FMODE_BSCAN2) ? 0x80 : 0);
3576 lofsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
3577 }
3578 }
3579 copl[cop_spr0ptrh].w[1] = highw(pl);
3580 copl[cop_spr0ptrl].w[1] = loww(pl);
3581 if (par->bplcon0 & BPC0_LACE) {
3582 cops[cop_spr0ptrh].w[1] = highw(ps);
3583 cops[cop_spr0ptrl].w[1] = loww(ps);
3584 }
3585}
3586
3587
3588 /*
3589 * Initialise the Copper Initialisation List
3590 */
3591
3592static void __init ami_init_copper(void)
3593{
3594 copins *cop = copdisplay.init;
3595 u_long p;
3596 int i;
3597
3598 if (!IS_OCS) {
3599 (cop++)->l = CMOVE(BPC0_COLOR | BPC0_SHRES | BPC0_ECSENA, bplcon0);
3600 (cop++)->l = CMOVE(0x0181, diwstrt);
3601 (cop++)->l = CMOVE(0x0281, diwstop);
3602 (cop++)->l = CMOVE(0x0000, diwhigh);
3603 } else
3604 (cop++)->l = CMOVE(BPC0_COLOR, bplcon0);
3605 p = ZTWO_PADDR(dummysprite);
3606 for (i = 0; i < 8; i++) {
3607 (cop++)->l = CMOVE(0, spr[i].pos);
3608 (cop++)->l = CMOVE(highw(p), sprpt[i]);
3609 (cop++)->l = CMOVE2(loww(p), sprpt[i]);
3610 }
3611
3612 (cop++)->l = CMOVE(IF_SETCLR | IF_COPER, intreq);
3613 copdisplay.wait = cop;
3614 (cop++)->l = CEND;
3615 (cop++)->l = CMOVE(0, copjmp2);
3616 cop->l = CEND;
3617
3618 custom.cop1lc = (u_short *)ZTWO_PADDR(copdisplay.init);
3619 custom.copjmp1 = 0;
3620}
3621 3752
3622static void ami_reinit_copper(void) 3753unset_drvdata:
3623{ 3754 dev_set_drvdata(&pdev->dev, NULL);
3624 struct amifb_par *par = &currentpar; 3755 fb_dealloc_cmap(&info->cmap);
3625 3756free_irq:
3626 copdisplay.init[cip_bplcon0].w[1] = ~(BPC0_BPU3 | BPC0_BPU2 | BPC0_BPU1 | BPC0_BPU0) & par->bplcon0; 3757 free_irq(IRQ_AMIGA_COPPER, info->par);
3627 copdisplay.wait->l = CWAIT(32, par->diwstrt_v-4); 3758disable_dma:
3759 custom.dmacon = DMAF_ALL | DMAF_MASTER;
3760 if (videomemory)
3761 iounmap((void *)videomemory);
3762 chipfree();
3763release:
3764 framebuffer_release(info);
3765 return err;
3628} 3766}
3629 3767
3630 /*
3631 * Build the Copper List
3632 */
3633
3634static void ami_build_copper(void)
3635{
3636 struct amifb_par *par = &currentpar;
3637 copins *copl, *cops;
3638 u_long p;
3639
3640 currentcop = 1 - currentcop;
3641
3642 copl = copdisplay.list[currentcop][1];
3643
3644 (copl++)->l = CWAIT(0, 10);
3645 (copl++)->l = CMOVE(par->bplcon0, bplcon0);
3646 (copl++)->l = CMOVE(0, sprpt[0]);
3647 (copl++)->l = CMOVE2(0, sprpt[0]);
3648
3649 if (par->bplcon0 & BPC0_LACE) {
3650 cops = copdisplay.list[currentcop][0];
3651
3652 (cops++)->l = CWAIT(0, 10);
3653 (cops++)->l = CMOVE(par->bplcon0, bplcon0);
3654 (cops++)->l = CMOVE(0, sprpt[0]);
3655 (cops++)->l = CMOVE2(0, sprpt[0]);
3656
3657 (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v+1), diwstrt);
3658 (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v+1), diwstop);
3659 (cops++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
3660 (cops++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
3661 if (!IS_OCS) {
3662 (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v+1,
3663 par->diwstop_h, par->diwstop_v+1), diwhigh);
3664 (cops++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
3665 par->diwstop_h, par->diwstop_v), diwhigh);
3666#if 0
3667 if (par->beamcon0 & BMC0_VARBEAMEN) {
3668 (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
3669 (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt+1), vbstrt);
3670 (copl++)->l = CMOVE(vbstop2hw(par->vbstop+1), vbstop);
3671 (cops++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
3672 (cops++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
3673 (cops++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
3674 }
3675#endif
3676 }
3677 p = ZTWO_PADDR(copdisplay.list[currentcop][0]);
3678 (copl++)->l = CMOVE(highw(p), cop2lc);
3679 (copl++)->l = CMOVE2(loww(p), cop2lc);
3680 p = ZTWO_PADDR(copdisplay.list[currentcop][1]);
3681 (cops++)->l = CMOVE(highw(p), cop2lc);
3682 (cops++)->l = CMOVE2(loww(p), cop2lc);
3683 copdisplay.rebuild[0] = cops;
3684 } else {
3685 (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
3686 (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
3687 if (!IS_OCS) {
3688 (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
3689 par->diwstop_h, par->diwstop_v), diwhigh);
3690#if 0
3691 if (par->beamcon0 & BMC0_VARBEAMEN) {
3692 (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
3693 (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
3694 (copl++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
3695 }
3696#endif
3697 }
3698 }
3699 copdisplay.rebuild[1] = copl;
3700
3701 ami_update_par();
3702 ami_rebuild_copper();
3703}
3704
3705 /*
3706 * Rebuild the Copper List
3707 *
3708 * We only change the things that are not static
3709 */
3710
3711static void ami_rebuild_copper(void)
3712{
3713 struct amifb_par *par = &currentpar;
3714 copins *copl, *cops;
3715 u_short line, h_end1, h_end2;
3716 short i;
3717 u_long p;
3718
3719 if (IS_AGA && maxfmode + par->clk_shift == 0)
3720 h_end1 = par->diwstrt_h-64;
3721 else
3722 h_end1 = par->htotal-32;
3723 h_end2 = par->ddfstop+64;
3724
3725 ami_set_sprite();
3726
3727 copl = copdisplay.rebuild[1];
3728 p = par->bplpt0;
3729 if (par->vmode & FB_VMODE_YWRAP) {
3730 if ((par->vyres-par->yoffset) != 1 || !mod2(par->diwstrt_v)) {
3731 if (par->yoffset > par->vyres-par->yres) {
3732 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
3733 (copl++)->l = CMOVE(highw(p), bplpt[i]);
3734 (copl++)->l = CMOVE2(loww(p), bplpt[i]);
3735 }
3736 line = par->diwstrt_v + ((par->vyres-par->yoffset)<<par->line_shift) - 1;
3737 while (line >= 512) {
3738 (copl++)->l = CWAIT(h_end1, 510);
3739 line -= 512;
3740 }
3741 if (line >= 510 && IS_AGA && maxfmode + par->clk_shift == 0)
3742 (copl++)->l = CWAIT(h_end1, line);
3743 else
3744 (copl++)->l = CWAIT(h_end2, line);
3745 p = par->bplpt0wrap;
3746 }
3747 } else p = par->bplpt0wrap;
3748 }
3749 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
3750 (copl++)->l = CMOVE(highw(p), bplpt[i]);
3751 (copl++)->l = CMOVE2(loww(p), bplpt[i]);
3752 }
3753 copl->l = CEND;
3754
3755 if (par->bplcon0 & BPC0_LACE) {
3756 cops = copdisplay.rebuild[0];
3757 p = par->bplpt0;
3758 if (mod2(par->diwstrt_v))
3759 p -= par->next_line;
3760 else
3761 p += par->next_line;
3762 if (par->vmode & FB_VMODE_YWRAP) {
3763 if ((par->vyres-par->yoffset) != 1 || mod2(par->diwstrt_v)) {
3764 if (par->yoffset > par->vyres-par->yres+1) {
3765 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
3766 (cops++)->l = CMOVE(highw(p), bplpt[i]);
3767 (cops++)->l = CMOVE2(loww(p), bplpt[i]);
3768 }
3769 line = par->diwstrt_v + ((par->vyres-par->yoffset)<<par->line_shift) - 2;
3770 while (line >= 512) {
3771 (cops++)->l = CWAIT(h_end1, 510);
3772 line -= 512;
3773 }
3774 if (line > 510 && IS_AGA && maxfmode + par->clk_shift == 0)
3775 (cops++)->l = CWAIT(h_end1, line);
3776 else
3777 (cops++)->l = CWAIT(h_end2, line);
3778 p = par->bplpt0wrap;
3779 if (mod2(par->diwstrt_v+par->vyres-par->yoffset))
3780 p -= par->next_line;
3781 else
3782 p += par->next_line;
3783 }
3784 } else p = par->bplpt0wrap - par->next_line;
3785 }
3786 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
3787 (cops++)->l = CMOVE(highw(p), bplpt[i]);
3788 (cops++)->l = CMOVE2(loww(p), bplpt[i]);
3789 }
3790 cops->l = CEND;
3791 }
3792}
3793 3768
3794static int __exit amifb_remove(struct platform_device *pdev) 3769static int __exit amifb_remove(struct platform_device *pdev)
3795{ 3770{
3796 unregister_framebuffer(&fb_info); 3771 struct fb_info *info = dev_get_drvdata(&pdev->dev);
3797 amifb_deinit(pdev); 3772
3773 unregister_framebuffer(info);
3774 dev_set_drvdata(&pdev->dev, NULL);
3775 fb_dealloc_cmap(&info->cmap);
3776 free_irq(IRQ_AMIGA_COPPER, info->par);
3777 custom.dmacon = DMAF_ALL | DMAF_MASTER;
3778 if (videomemory)
3779 iounmap((void *)videomemory);
3780 chipfree();
3781 framebuffer_release(info);
3798 amifb_video_off(); 3782 amifb_video_off();
3799 return 0; 3783 return 0;
3800} 3784}
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index 63409c122ae8..0d7b20d4285d 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -100,8 +100,11 @@ static int atmel_bl_update_status(struct backlight_device *bl)
100 brightness = 0; 100 brightness = 0;
101 101
102 lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, brightness); 102 lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, brightness);
103 lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 103 if (contrast_ctr & ATMEL_LCDC_POL_POSITIVE)
104 lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR,
104 brightness ? contrast_ctr : 0); 105 brightness ? contrast_ctr : 0);
106 else
107 lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr);
105 108
106 bl->props.fb_blank = bl->props.power = sinfo->bl_power = power; 109 bl->props.fb_blank = bl->props.power = sinfo->bl_power = power;
107 110
@@ -682,14 +685,30 @@ static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red,
682 685
683 case FB_VISUAL_PSEUDOCOLOR: 686 case FB_VISUAL_PSEUDOCOLOR:
684 if (regno < 256) { 687 if (regno < 256) {
685 val = ((red >> 11) & 0x001f); 688 if (cpu_is_at91sam9261() || cpu_is_at91sam9263()
686 val |= ((green >> 6) & 0x03e0); 689 || cpu_is_at91sam9rl()) {
687 val |= ((blue >> 1) & 0x7c00); 690 /* old style I+BGR:555 */
688 691 val = ((red >> 11) & 0x001f);
689 /* 692 val |= ((green >> 6) & 0x03e0);
690 * TODO: intensity bit. Maybe something like 693 val |= ((blue >> 1) & 0x7c00);
691 * ~(red[10] ^ green[10] ^ blue[10]) & 1 694
692 */ 695 /*
696 * TODO: intensity bit. Maybe something like
697 * ~(red[10] ^ green[10] ^ blue[10]) & 1
698 */
699 } else {
700 /* new style BGR:565 / RGB:565 */
701 if (sinfo->lcd_wiring_mode ==
702 ATMEL_LCDC_WIRING_RGB) {
703 val = ((blue >> 11) & 0x001f);
704 val |= ((red >> 0) & 0xf800);
705 } else {
706 val = ((red >> 11) & 0x001f);
707 val |= ((blue >> 0) & 0xf800);
708 }
709
710 val |= ((green >> 5) & 0x07e0);
711 }
693 712
694 lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val); 713 lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val);
695 ret = 0; 714 ret = 0;
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c
index 6fb499e7678f..738c8ce7d132 100644
--- a/drivers/video/cirrusfb.c
+++ b/drivers/video/cirrusfb.c
@@ -280,52 +280,74 @@ MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
280#endif /* CONFIG_PCI */ 280#endif /* CONFIG_PCI */
281 281
282#ifdef CONFIG_ZORRO 282#ifdef CONFIG_ZORRO
283static const struct zorro_device_id cirrusfb_zorro_table[] = { 283struct zorrocl {
284 enum cirrus_board type; /* Board type */
285 u32 regoffset; /* Offset of registers in first Zorro device */
286 u32 ramsize; /* Size of video RAM in first Zorro device */
287 /* If zero, use autoprobe on RAM device */
288 u32 ramoffset; /* Offset of video RAM in first Zorro device */
289 zorro_id ramid; /* Zorro ID of RAM device */
290 zorro_id ramid2; /* Zorro ID of optional second RAM device */
291};
292
293static const struct zorrocl zcl_sd64 __devinitconst = {
294 .type = BT_SD64,
295 .ramid = ZORRO_PROD_HELFRICH_SD64_RAM,
296};
297
298static const struct zorrocl zcl_piccolo __devinitconst = {
299 .type = BT_PICCOLO,
300 .ramid = ZORRO_PROD_HELFRICH_PICCOLO_RAM,
301};
302
303static const struct zorrocl zcl_picasso __devinitconst = {
304 .type = BT_PICASSO,
305 .ramid = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
306};
307
308static const struct zorrocl zcl_spectrum __devinitconst = {
309 .type = BT_SPECTRUM,
310 .ramid = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
311};
312
313static const struct zorrocl zcl_picasso4_z3 __devinitconst = {
314 .type = BT_PICASSO4,
315 .regoffset = 0x00600000,
316 .ramsize = 4 * MB_,
317 .ramoffset = 0x01000000, /* 0x02000000 for 64 MiB boards */
318};
319
320static const struct zorrocl zcl_picasso4_z2 __devinitconst = {
321 .type = BT_PICASSO4,
322 .regoffset = 0x10000,
323 .ramid = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM1,
324 .ramid2 = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM2,
325};
326
327
328static const struct zorro_device_id cirrusfb_zorro_table[] __devinitconst = {
284 { 329 {
285 .id = ZORRO_PROD_HELFRICH_SD64_RAM, 330 .id = ZORRO_PROD_HELFRICH_SD64_REG,
286 .driver_data = BT_SD64, 331 .driver_data = (unsigned long)&zcl_sd64,
287 }, { 332 }, {
288 .id = ZORRO_PROD_HELFRICH_PICCOLO_RAM, 333 .id = ZORRO_PROD_HELFRICH_PICCOLO_REG,
289 .driver_data = BT_PICCOLO, 334 .driver_data = (unsigned long)&zcl_piccolo,
290 }, { 335 }, {
291 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM, 336 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
292 .driver_data = BT_PICASSO, 337 .driver_data = (unsigned long)&zcl_picasso,
293 }, { 338 }, {
294 .id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM, 339 .id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
295 .driver_data = BT_SPECTRUM, 340 .driver_data = (unsigned long)&zcl_spectrum,
296 }, { 341 }, {
297 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3, 342 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
298 .driver_data = BT_PICASSO4, 343 .driver_data = (unsigned long)&zcl_picasso4_z3,
344 }, {
345 .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_REG,
346 .driver_data = (unsigned long)&zcl_picasso4_z2,
299 }, 347 },
300 { 0 } 348 { 0 }
301}; 349};
302MODULE_DEVICE_TABLE(zorro, cirrusfb_zorro_table); 350MODULE_DEVICE_TABLE(zorro, cirrusfb_zorro_table);
303
304static const struct {
305 zorro_id id2;
306 unsigned long size;
307} cirrusfb_zorro_table2[] = {
308 [BT_SD64] = {
309 .id2 = ZORRO_PROD_HELFRICH_SD64_REG,
310 .size = 0x400000
311 },
312 [BT_PICCOLO] = {
313 .id2 = ZORRO_PROD_HELFRICH_PICCOLO_REG,
314 .size = 0x200000
315 },
316 [BT_PICASSO] = {
317 .id2 = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
318 .size = 0x200000
319 },
320 [BT_SPECTRUM] = {
321 .id2 = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
322 .size = 0x200000
323 },
324 [BT_PICASSO4] = {
325 .id2 = 0,
326 .size = 0x400000
327 }
328};
329#endif /* CONFIG_ZORRO */ 351#endif /* CONFIG_ZORRO */
330 352
331#ifdef CIRRUSFB_DEBUG 353#ifdef CIRRUSFB_DEBUG
@@ -1956,16 +1978,12 @@ static void cirrusfb_zorro_unmap(struct fb_info *info)
1956 struct cirrusfb_info *cinfo = info->par; 1978 struct cirrusfb_info *cinfo = info->par;
1957 struct zorro_dev *zdev = to_zorro_dev(info->device); 1979 struct zorro_dev *zdev = to_zorro_dev(info->device);
1958 1980
1959 zorro_release_device(zdev); 1981 if (info->fix.smem_start > 16 * MB_)
1960
1961 if (cinfo->btype == BT_PICASSO4) {
1962 cinfo->regbase -= 0x600000;
1963 iounmap((void *)cinfo->regbase);
1964 iounmap(info->screen_base); 1982 iounmap(info->screen_base);
1965 } else { 1983 if (info->fix.mmio_start > 16 * MB_)
1966 if (zorro_resource_start(zdev) > 0x01000000) 1984 iounmap(cinfo->regbase);
1967 iounmap(info->screen_base); 1985
1968 } 1986 zorro_release_device(zdev);
1969} 1987}
1970#endif /* CONFIG_ZORRO */ 1988#endif /* CONFIG_ZORRO */
1971 1989
@@ -2222,115 +2240,116 @@ static struct pci_driver cirrusfb_pci_driver = {
2222static int __devinit cirrusfb_zorro_register(struct zorro_dev *z, 2240static int __devinit cirrusfb_zorro_register(struct zorro_dev *z,
2223 const struct zorro_device_id *ent) 2241 const struct zorro_device_id *ent)
2224{ 2242{
2225 struct cirrusfb_info *cinfo;
2226 struct fb_info *info; 2243 struct fb_info *info;
2244 int error;
2245 const struct zorrocl *zcl;
2227 enum cirrus_board btype; 2246 enum cirrus_board btype;
2228 struct zorro_dev *z2 = NULL; 2247 unsigned long regbase, ramsize, rambase;
2229 unsigned long board_addr, board_size, size; 2248 struct cirrusfb_info *cinfo;
2230 int ret;
2231
2232 btype = ent->driver_data;
2233 if (cirrusfb_zorro_table2[btype].id2)
2234 z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL);
2235 size = cirrusfb_zorro_table2[btype].size;
2236 2249
2237 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev); 2250 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
2238 if (!info) { 2251 if (!info) {
2239 printk(KERN_ERR "cirrusfb: could not allocate memory\n"); 2252 printk(KERN_ERR "cirrusfb: could not allocate memory\n");
2240 ret = -ENOMEM; 2253 return -ENOMEM;
2241 goto err_out; 2254 }
2255
2256 zcl = (const struct zorrocl *)ent->driver_data;
2257 btype = zcl->type;
2258 regbase = zorro_resource_start(z) + zcl->regoffset;
2259 ramsize = zcl->ramsize;
2260 if (ramsize) {
2261 rambase = zorro_resource_start(z) + zcl->ramoffset;
2262 if (zorro_resource_len(z) == 64 * MB_) {
2263 /* Quirk for 64 MiB Picasso IV */
2264 rambase += zcl->ramoffset;
2265 }
2266 } else {
2267 struct zorro_dev *ram = zorro_find_device(zcl->ramid, NULL);
2268 if (!ram || !zorro_resource_len(ram)) {
2269 dev_err(info->device, "No video RAM found\n");
2270 error = -ENODEV;
2271 goto err_release_fb;
2272 }
2273 rambase = zorro_resource_start(ram);
2274 ramsize = zorro_resource_len(ram);
2275 if (zcl->ramid2 &&
2276 (ram = zorro_find_device(zcl->ramid2, NULL))) {
2277 if (zorro_resource_start(ram) != rambase + ramsize) {
2278 dev_warn(info->device,
2279 "Skipping non-contiguous RAM at %pR\n",
2280 &ram->resource);
2281 } else {
2282 ramsize += zorro_resource_len(ram);
2283 }
2284 }
2242 } 2285 }
2243 2286
2244 dev_info(info->device, "%s board detected\n", 2287 dev_info(info->device,
2245 cirrusfb_board_info[btype].name); 2288 "%s board detected, REG at 0x%lx, %lu MiB RAM at 0x%lx\n",
2246 2289 cirrusfb_board_info[btype].name, regbase, ramsize / MB_,
2247 cinfo = info->par; 2290 rambase);
2248 cinfo->btype = btype;
2249
2250 assert(z);
2251 assert(btype != BT_NONE);
2252
2253 board_addr = zorro_resource_start(z);
2254 board_size = zorro_resource_len(z);
2255 info->screen_size = size;
2256 2291
2257 if (!zorro_request_device(z, "cirrusfb")) { 2292 if (!zorro_request_device(z, "cirrusfb")) {
2258 dev_err(info->device, "cannot reserve region 0x%lx, abort\n", 2293 dev_err(info->device, "Cannot reserve %pR\n", &z->resource);
2259 board_addr); 2294 error = -EBUSY;
2260 ret = -EBUSY;
2261 goto err_release_fb; 2295 goto err_release_fb;
2262 } 2296 }
2263 2297
2264 ret = -EIO; 2298 cinfo = info->par;
2265 2299 cinfo->btype = btype;
2266 if (btype == BT_PICASSO4) {
2267 dev_info(info->device, " REG at $%lx\n", board_addr + 0x600000);
2268
2269 /* To be precise, for the P4 this is not the */
2270 /* begin of the board, but the begin of RAM. */
2271 /* for P4, map in its address space in 2 chunks (### TEST! ) */
2272 /* (note the ugly hardcoded 16M number) */
2273 cinfo->regbase = ioremap(board_addr, 16777216);
2274 if (!cinfo->regbase)
2275 goto err_release_region;
2276
2277 dev_dbg(info->device, "Virtual address for board set to: $%p\n",
2278 cinfo->regbase);
2279 cinfo->regbase += 0x600000;
2280 info->fix.mmio_start = board_addr + 0x600000;
2281
2282 info->fix.smem_start = board_addr + 16777216;
2283 info->screen_base = ioremap(info->fix.smem_start, 16777216);
2284 if (!info->screen_base)
2285 goto err_unmap_regbase;
2286 } else {
2287 dev_info(info->device, " REG at $%lx\n",
2288 (unsigned long) z2->resource.start);
2289
2290 info->fix.smem_start = board_addr;
2291 if (board_addr > 0x01000000)
2292 info->screen_base = ioremap(board_addr, board_size);
2293 else
2294 info->screen_base = (caddr_t) ZTWO_VADDR(board_addr);
2295 if (!info->screen_base)
2296 goto err_release_region;
2297 2300
2298 /* set address for REG area of board */ 2301 info->fix.mmio_start = regbase;
2299 cinfo->regbase = (caddr_t) ZTWO_VADDR(z2->resource.start); 2302 cinfo->regbase = regbase > 16 * MB_ ? ioremap(regbase, 64 * 1024)
2300 info->fix.mmio_start = z2->resource.start; 2303 : (caddr_t)ZTWO_VADDR(regbase);
2304 if (!cinfo->regbase) {
2305 dev_err(info->device, "Cannot map registers\n");
2306 error = -EIO;
2307 goto err_release_dev;
2308 }
2301 2309
2302 dev_dbg(info->device, "Virtual address for board set to: $%p\n", 2310 info->fix.smem_start = rambase;
2303 cinfo->regbase); 2311 info->screen_size = ramsize;
2312 info->screen_base = rambase > 16 * MB_ ? ioremap(rambase, ramsize)
2313 : (caddr_t)ZTWO_VADDR(rambase);
2314 if (!info->screen_base) {
2315 dev_err(info->device, "Cannot map video RAM\n");
2316 error = -EIO;
2317 goto err_unmap_reg;
2304 } 2318 }
2319
2305 cinfo->unmap = cirrusfb_zorro_unmap; 2320 cinfo->unmap = cirrusfb_zorro_unmap;
2306 2321
2307 dev_info(info->device, 2322 dev_info(info->device,
2308 "Cirrus Logic chipset on Zorro bus, RAM (%lu MB) at $%lx\n", 2323 "Cirrus Logic chipset on Zorro bus, RAM (%lu MiB) at 0x%lx\n",
2309 board_size / MB_, board_addr); 2324 ramsize / MB_, rambase);
2310
2311 zorro_set_drvdata(z, info);
2312 2325
2313 /* MCLK select etc. */ 2326 /* MCLK select etc. */
2314 if (cirrusfb_board_info[btype].init_sr1f) 2327 if (cirrusfb_board_info[btype].init_sr1f)
2315 vga_wseq(cinfo->regbase, CL_SEQR1F, 2328 vga_wseq(cinfo->regbase, CL_SEQR1F,
2316 cirrusfb_board_info[btype].sr1f); 2329 cirrusfb_board_info[btype].sr1f);
2317 2330
2318 ret = cirrusfb_register(info); 2331 error = cirrusfb_register(info);
2319 if (!ret) 2332 if (error) {
2320 return 0; 2333 dev_err(info->device, "Failed to register device, error %d\n",
2334 error);
2335 goto err_unmap_ram;
2336 }
2321 2337
2322 if (btype == BT_PICASSO4 || board_addr > 0x01000000) 2338 zorro_set_drvdata(z, info);
2339 return 0;
2340
2341err_unmap_ram:
2342 if (rambase > 16 * MB_)
2323 iounmap(info->screen_base); 2343 iounmap(info->screen_base);
2324 2344
2325err_unmap_regbase: 2345err_unmap_reg:
2326 if (btype == BT_PICASSO4) 2346 if (regbase > 16 * MB_)
2327 iounmap(cinfo->regbase - 0x600000); 2347 iounmap(cinfo->regbase);
2328err_release_region: 2348err_release_dev:
2329 release_region(board_addr, board_size); 2349 zorro_release_device(z);
2330err_release_fb: 2350err_release_fb:
2331 framebuffer_release(info); 2351 framebuffer_release(info);
2332err_out: 2352 return error;
2333 return ret;
2334} 2353}
2335 2354
2336void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z) 2355void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
@@ -2338,6 +2357,7 @@ void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
2338 struct fb_info *info = zorro_get_drvdata(z); 2357 struct fb_info *info = zorro_get_drvdata(z);
2339 2358
2340 cirrusfb_cleanup(info); 2359 cirrusfb_cleanup(info);
2360 zorro_set_drvdata(z, NULL);
2341} 2361}
2342 2362
2343static struct zorro_driver cirrusfb_zorro_driver = { 2363static struct zorro_driver cirrusfb_zorro_driver = {
diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c
index 7b2c40abae15..0c189b32a4c5 100644
--- a/drivers/video/controlfb.c
+++ b/drivers/video/controlfb.c
@@ -420,7 +420,7 @@ static int __init init_control(struct fb_info_control *p)
420 420
421 /* Try to pick a video mode out of NVRAM if we have one. */ 421 /* Try to pick a video mode out of NVRAM if we have one. */
422#ifdef CONFIG_NVRAM 422#ifdef CONFIG_NVRAM
423 if (default_cmode == CMODE_NVRAM){ 423 if (default_cmode == CMODE_NVRAM) {
424 cmode = nvram_read_byte(NV_CMODE); 424 cmode = nvram_read_byte(NV_CMODE);
425 if(cmode < CMODE_8 || cmode > CMODE_32) 425 if(cmode < CMODE_8 || cmode > CMODE_32)
426 cmode = CMODE_8; 426 cmode = CMODE_8;
diff --git a/drivers/video/display/Kconfig b/drivers/video/display/Kconfig
deleted file mode 100644
index f99af931d4f8..000000000000
--- a/drivers/video/display/Kconfig
+++ /dev/null
@@ -1,24 +0,0 @@
1#
2# Display drivers configuration
3#
4
5menu "Display device support"
6
7config DISPLAY_SUPPORT
8 tristate "Display panel/monitor support"
9 ---help---
10 This framework adds support for low-level control of a display.
11 This includes support for power.
12
13 Enable this to be able to choose the drivers for controlling the
14 physical display panel/monitor on some platforms. This not only
15 covers LCD displays for PDAs but also other types of displays
16 such as CRT, TVout etc.
17
18 To have support for your specific display panel you will have to
19 select the proper drivers which depend on this option.
20
21comment "Display hardware drivers"
22 depends on DISPLAY_SUPPORT
23
24endmenu
diff --git a/drivers/video/display/Makefile b/drivers/video/display/Makefile
deleted file mode 100644
index c0ea832bf171..000000000000
--- a/drivers/video/display/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
1# Display drivers
2
3display-objs := display-sysfs.o
4
5obj-$(CONFIG_DISPLAY_SUPPORT) += display.o
6
diff --git a/drivers/video/display/display-sysfs.c b/drivers/video/display/display-sysfs.c
deleted file mode 100644
index 0c647d7af0ee..000000000000
--- a/drivers/video/display/display-sysfs.c
+++ /dev/null
@@ -1,219 +0,0 @@
1/*
2 * display-sysfs.c - Display output driver sysfs interface
3 *
4 * Copyright (C) 2007 James Simmons <jsimmons@infradead.org>
5 *
6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or (at
11 * your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 *
22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23 */
24#include <linux/module.h>
25#include <linux/display.h>
26#include <linux/ctype.h>
27#include <linux/idr.h>
28#include <linux/err.h>
29#include <linux/kdev_t.h>
30#include <linux/slab.h>
31
32static ssize_t display_show_name(struct device *dev,
33 struct device_attribute *attr, char *buf)
34{
35 struct display_device *dsp = dev_get_drvdata(dev);
36 return snprintf(buf, PAGE_SIZE, "%s\n", dsp->name);
37}
38
39static ssize_t display_show_type(struct device *dev,
40 struct device_attribute *attr, char *buf)
41{
42 struct display_device *dsp = dev_get_drvdata(dev);
43 return snprintf(buf, PAGE_SIZE, "%s\n", dsp->type);
44}
45
46static ssize_t display_show_contrast(struct device *dev,
47 struct device_attribute *attr, char *buf)
48{
49 struct display_device *dsp = dev_get_drvdata(dev);
50 ssize_t rc = -ENXIO;
51
52 mutex_lock(&dsp->lock);
53 if (likely(dsp->driver) && dsp->driver->get_contrast)
54 rc = sprintf(buf, "%d\n", dsp->driver->get_contrast(dsp));
55 mutex_unlock(&dsp->lock);
56 return rc;
57}
58
59static ssize_t display_store_contrast(struct device *dev,
60 struct device_attribute *attr,
61 const char *buf, size_t count)
62{
63 struct display_device *dsp = dev_get_drvdata(dev);
64 ssize_t ret = -EINVAL, size;
65 int contrast;
66 char *endp;
67
68 contrast = simple_strtoul(buf, &endp, 0);
69 size = endp - buf;
70
71 if (isspace(*endp))
72 size++;
73
74 if (size != count)
75 return ret;
76
77 mutex_lock(&dsp->lock);
78 if (likely(dsp->driver && dsp->driver->set_contrast)) {
79 pr_debug("display: set contrast to %d\n", contrast);
80 dsp->driver->set_contrast(dsp, contrast);
81 ret = count;
82 }
83 mutex_unlock(&dsp->lock);
84 return ret;
85}
86
87static ssize_t display_show_max_contrast(struct device *dev,
88 struct device_attribute *attr,
89 char *buf)
90{
91 struct display_device *dsp = dev_get_drvdata(dev);
92 ssize_t rc = -ENXIO;
93
94 mutex_lock(&dsp->lock);
95 if (likely(dsp->driver))
96 rc = sprintf(buf, "%d\n", dsp->driver->max_contrast);
97 mutex_unlock(&dsp->lock);
98 return rc;
99}
100
101static struct device_attribute display_attrs[] = {
102 __ATTR(name, S_IRUGO, display_show_name, NULL),
103 __ATTR(type, S_IRUGO, display_show_type, NULL),
104 __ATTR(contrast, S_IRUGO | S_IWUSR, display_show_contrast, display_store_contrast),
105 __ATTR(max_contrast, S_IRUGO, display_show_max_contrast, NULL),
106};
107
108static int display_suspend(struct device *dev, pm_message_t state)
109{
110 struct display_device *dsp = dev_get_drvdata(dev);
111
112 mutex_lock(&dsp->lock);
113 if (likely(dsp->driver->suspend))
114 dsp->driver->suspend(dsp, state);
115 mutex_unlock(&dsp->lock);
116 return 0;
117};
118
119static int display_resume(struct device *dev)
120{
121 struct display_device *dsp = dev_get_drvdata(dev);
122
123 mutex_lock(&dsp->lock);
124 if (likely(dsp->driver->resume))
125 dsp->driver->resume(dsp);
126 mutex_unlock(&dsp->lock);
127 return 0;
128};
129
130static struct mutex allocated_dsp_lock;
131static DEFINE_IDR(allocated_dsp);
132static struct class *display_class;
133
134struct display_device *display_device_register(struct display_driver *driver,
135 struct device *parent, void *devdata)
136{
137 struct display_device *new_dev = NULL;
138 int ret = -EINVAL;
139
140 if (unlikely(!driver))
141 return ERR_PTR(ret);
142
143 mutex_lock(&allocated_dsp_lock);
144 ret = idr_pre_get(&allocated_dsp, GFP_KERNEL);
145 mutex_unlock(&allocated_dsp_lock);
146 if (!ret)
147 return ERR_PTR(ret);
148
149 new_dev = kzalloc(sizeof(struct display_device), GFP_KERNEL);
150 if (likely(new_dev) && unlikely(driver->probe(new_dev, devdata))) {
151 // Reserve the index for this display
152 mutex_lock(&allocated_dsp_lock);
153 ret = idr_get_new(&allocated_dsp, new_dev, &new_dev->idx);
154 mutex_unlock(&allocated_dsp_lock);
155
156 if (!ret) {
157 new_dev->dev = device_create(display_class, parent,
158 MKDEV(0, 0), new_dev,
159 "display%d", new_dev->idx);
160 if (!IS_ERR(new_dev->dev)) {
161 new_dev->parent = parent;
162 new_dev->driver = driver;
163 mutex_init(&new_dev->lock);
164 return new_dev;
165 }
166 mutex_lock(&allocated_dsp_lock);
167 idr_remove(&allocated_dsp, new_dev->idx);
168 mutex_unlock(&allocated_dsp_lock);
169 ret = -EINVAL;
170 }
171 }
172 kfree(new_dev);
173 return ERR_PTR(ret);
174}
175EXPORT_SYMBOL(display_device_register);
176
177void display_device_unregister(struct display_device *ddev)
178{
179 if (!ddev)
180 return;
181 // Free device
182 mutex_lock(&ddev->lock);
183 device_unregister(ddev->dev);
184 mutex_unlock(&ddev->lock);
185 // Mark device index as available
186 mutex_lock(&allocated_dsp_lock);
187 idr_remove(&allocated_dsp, ddev->idx);
188 mutex_unlock(&allocated_dsp_lock);
189 kfree(ddev);
190}
191EXPORT_SYMBOL(display_device_unregister);
192
193static int __init display_class_init(void)
194{
195 display_class = class_create(THIS_MODULE, "display");
196 if (IS_ERR(display_class)) {
197 printk(KERN_ERR "Failed to create display class\n");
198 display_class = NULL;
199 return -EINVAL;
200 }
201 display_class->dev_attrs = display_attrs;
202 display_class->suspend = display_suspend;
203 display_class->resume = display_resume;
204 mutex_init(&allocated_dsp_lock);
205 return 0;
206}
207
208static void __exit display_class_exit(void)
209{
210 class_destroy(display_class);
211}
212
213module_init(display_class_init);
214module_exit(display_class_exit);
215
216MODULE_DESCRIPTION("Display Hardware handling");
217MODULE_AUTHOR("James Simmons <jsimmons@infradead.org>");
218MODULE_LICENSE("GPL");
219
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index ad936295d8f4..ac9141b85356 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -967,6 +967,20 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
967 memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) { 967 memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) {
968 u32 activate = var->activate; 968 u32 activate = var->activate;
969 969
970 /* When using FOURCC mode, make sure the red, green, blue and
971 * transp fields are set to 0.
972 */
973 if ((info->fix.capabilities & FB_CAP_FOURCC) &&
974 var->grayscale > 1) {
975 if (var->red.offset || var->green.offset ||
976 var->blue.offset || var->transp.offset ||
977 var->red.length || var->green.length ||
978 var->blue.length || var->transp.length ||
979 var->red.msb_right || var->green.msb_right ||
980 var->blue.msb_right || var->transp.msb_right)
981 return -EINVAL;
982 }
983
970 if (!info->fbops->fb_check_var) { 984 if (!info->fbops->fb_check_var) {
971 *var = info->var; 985 *var = info->var;
972 goto done; 986 goto done;
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index a16beeb5f548..acf292bfba02 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -36,8 +36,7 @@
36#include <linux/fsl-diu-fb.h> 36#include <linux/fsl-diu-fb.h>
37#include "edid.h" 37#include "edid.h"
38 38
39#define FSL_AOI_NUM 6 /* 5 AOIs and one dummy AOI */ 39#define NUM_AOIS 5 /* 1 for plane 0, 2 for planes 1 & 2 each */
40 /* 1 for plane 0, 2 for plane 1&2 each */
41 40
42/* HW cursor parameters */ 41/* HW cursor parameters */
43#define MAX_CURS 32 42#define MAX_CURS 32
@@ -49,12 +48,6 @@
49#define INT_PARERR 0x08 /* Display parameters error interrupt */ 48#define INT_PARERR 0x08 /* Display parameters error interrupt */
50#define INT_LS_BF_VS 0x10 /* Lines before vsync. interrupt */ 49#define INT_LS_BF_VS 0x10 /* Lines before vsync. interrupt */
51 50
52struct diu_addr {
53 void *vaddr; /* Virtual address */
54 dma_addr_t paddr; /* Physical address */
55 __u32 offset;
56};
57
58/* 51/*
59 * List of supported video modes 52 * List of supported video modes
60 * 53 *
@@ -330,23 +323,6 @@ static unsigned int d_cache_line_size;
330 323
331static DEFINE_SPINLOCK(diu_lock); 324static DEFINE_SPINLOCK(diu_lock);
332 325
333struct fsl_diu_data {
334 struct fb_info *fsl_diu_info[FSL_AOI_NUM - 1];
335 /*FSL_AOI_NUM has one dummy AOI */
336 struct device_attribute dev_attr;
337 struct diu_ad *dummy_ad;
338 void *dummy_aoi_virt;
339 unsigned int irq;
340 int fb_enabled;
341 enum fsl_diu_monitor_port monitor_port;
342 struct diu __iomem *diu_reg;
343 spinlock_t reg_lock;
344 struct diu_addr ad;
345 struct diu_addr gamma;
346 struct diu_addr pallete;
347 struct diu_addr cursor;
348};
349
350enum mfb_index { 326enum mfb_index {
351 PLANE0 = 0, /* Plane 0, only one AOI that fills the screen */ 327 PLANE0 = 0, /* Plane 0, only one AOI that fills the screen */
352 PLANE1_AOI0, /* Plane 1, first AOI */ 328 PLANE1_AOI0, /* Plane 1, first AOI */
@@ -370,6 +346,42 @@ struct mfb_info {
370 u8 *edid_data; 346 u8 *edid_data;
371}; 347};
372 348
349/**
350 * struct fsl_diu_data - per-DIU data structure
351 * @dma_addr: DMA address of this structure
352 * @fsl_diu_info: fb_info objects, one per AOI
353 * @dev_attr: sysfs structure
354 * @irq: IRQ
355 * @monitor_port: the monitor port this DIU is connected to
356 * @diu_reg: pointer to the DIU hardware registers
357 * @reg_lock: spinlock for register access
358 * @dummy_aoi: video buffer for the 4x4 32-bit dummy AOI
359 * dummy_ad: DIU Area Descriptor for the dummy AOI
360 * @ad[]: Area Descriptors for each real AOI
361 * @gamma: gamma color table
362 * @cursor: hardware cursor data
363 *
364 * This data structure must be allocated with 32-byte alignment, so that the
365 * internal fields can be aligned properly.
366 */
367struct fsl_diu_data {
368 dma_addr_t dma_addr;
369 struct fb_info fsl_diu_info[NUM_AOIS];
370 struct mfb_info mfb[NUM_AOIS];
371 struct device_attribute dev_attr;
372 unsigned int irq;
373 enum fsl_diu_monitor_port monitor_port;
374 struct diu __iomem *diu_reg;
375 spinlock_t reg_lock;
376 u8 dummy_aoi[4 * 4 * 4];
377 struct diu_ad dummy_ad __aligned(8);
378 struct diu_ad ad[NUM_AOIS] __aligned(8);
379 u8 gamma[256 * 3] __aligned(32);
380 u8 cursor[MAX_CURS * MAX_CURS * 2] __aligned(32);
381} __aligned(32);
382
383/* Determine the DMA address of a member of the fsl_diu_data structure */
384#define DMA_ADDR(p, f) ((p)->dma_addr + offsetof(struct fsl_diu_data, f))
373 385
374static struct mfb_info mfb_template[] = { 386static struct mfb_info mfb_template[] = {
375 { 387 {
@@ -449,37 +461,6 @@ static enum fsl_diu_monitor_port fsl_diu_name_to_port(const char *s)
449 return diu_ops.valid_monitor_port(port); 461 return diu_ops.valid_monitor_port(port);
450} 462}
451 463
452/**
453 * fsl_diu_alloc - allocate memory for the DIU
454 * @size: number of bytes to allocate
455 * @param: returned physical address of memory
456 *
457 * This function allocates a physically-contiguous block of memory.
458 */
459static void *fsl_diu_alloc(size_t size, phys_addr_t *phys)
460{
461 void *virt;
462
463 virt = alloc_pages_exact(size, GFP_DMA | __GFP_ZERO);
464 if (virt)
465 *phys = virt_to_phys(virt);
466
467 return virt;
468}
469
470/**
471 * fsl_diu_free - release DIU memory
472 * @virt: pointer returned by fsl_diu_alloc()
473 * @size: number of bytes allocated by fsl_diu_alloc()
474 *
475 * This function releases memory allocated by fsl_diu_alloc().
476 */
477static void fsl_diu_free(void *virt, size_t size)
478{
479 if (virt && size)
480 free_pages_exact(virt, size);
481}
482
483/* 464/*
484 * Workaround for failed writing desc register of planes. 465 * Workaround for failed writing desc register of planes.
485 * Needed with MPC5121 DIU rev 2.0 silicon. 466 * Needed with MPC5121 DIU rev 2.0 silicon.
@@ -495,8 +476,8 @@ static void fsl_diu_enable_panel(struct fb_info *info)
495{ 476{
496 struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par; 477 struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par;
497 struct diu_ad *ad = mfbi->ad; 478 struct diu_ad *ad = mfbi->ad;
498 struct fsl_diu_data *machine_data = mfbi->parent; 479 struct fsl_diu_data *data = mfbi->parent;
499 struct diu __iomem *hw = machine_data->diu_reg; 480 struct diu __iomem *hw = data->diu_reg;
500 481
501 switch (mfbi->index) { 482 switch (mfbi->index) {
502 case PLANE0: 483 case PLANE0:
@@ -504,7 +485,7 @@ static void fsl_diu_enable_panel(struct fb_info *info)
504 wr_reg_wa(&hw->desc[0], ad->paddr); 485 wr_reg_wa(&hw->desc[0], ad->paddr);
505 break; 486 break;
506 case PLANE1_AOI0: 487 case PLANE1_AOI0:
507 cmfbi = machine_data->fsl_diu_info[2]->par; 488 cmfbi = &data->mfb[2];
508 if (hw->desc[1] != ad->paddr) { /* AOI0 closed */ 489 if (hw->desc[1] != ad->paddr) { /* AOI0 closed */
509 if (cmfbi->count > 0) /* AOI1 open */ 490 if (cmfbi->count > 0) /* AOI1 open */
510 ad->next_ad = 491 ad->next_ad =
@@ -515,7 +496,7 @@ static void fsl_diu_enable_panel(struct fb_info *info)
515 } 496 }
516 break; 497 break;
517 case PLANE2_AOI0: 498 case PLANE2_AOI0:
518 cmfbi = machine_data->fsl_diu_info[4]->par; 499 cmfbi = &data->mfb[4];
519 if (hw->desc[2] != ad->paddr) { /* AOI0 closed */ 500 if (hw->desc[2] != ad->paddr) { /* AOI0 closed */
520 if (cmfbi->count > 0) /* AOI1 open */ 501 if (cmfbi->count > 0) /* AOI1 open */
521 ad->next_ad = 502 ad->next_ad =
@@ -526,17 +507,17 @@ static void fsl_diu_enable_panel(struct fb_info *info)
526 } 507 }
527 break; 508 break;
528 case PLANE1_AOI1: 509 case PLANE1_AOI1:
529 pmfbi = machine_data->fsl_diu_info[1]->par; 510 pmfbi = &data->mfb[1];
530 ad->next_ad = 0; 511 ad->next_ad = 0;
531 if (hw->desc[1] == machine_data->dummy_ad->paddr) 512 if (hw->desc[1] == data->dummy_ad.paddr)
532 wr_reg_wa(&hw->desc[1], ad->paddr); 513 wr_reg_wa(&hw->desc[1], ad->paddr);
533 else /* AOI0 open */ 514 else /* AOI0 open */
534 pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); 515 pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
535 break; 516 break;
536 case PLANE2_AOI1: 517 case PLANE2_AOI1:
537 pmfbi = machine_data->fsl_diu_info[3]->par; 518 pmfbi = &data->mfb[3];
538 ad->next_ad = 0; 519 ad->next_ad = 0;
539 if (hw->desc[2] == machine_data->dummy_ad->paddr) 520 if (hw->desc[2] == data->dummy_ad.paddr)
540 wr_reg_wa(&hw->desc[2], ad->paddr); 521 wr_reg_wa(&hw->desc[2], ad->paddr);
541 else /* AOI0 was open */ 522 else /* AOI0 was open */
542 pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); 523 pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
@@ -548,52 +529,52 @@ static void fsl_diu_disable_panel(struct fb_info *info)
548{ 529{
549 struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par; 530 struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par;
550 struct diu_ad *ad = mfbi->ad; 531 struct diu_ad *ad = mfbi->ad;
551 struct fsl_diu_data *machine_data = mfbi->parent; 532 struct fsl_diu_data *data = mfbi->parent;
552 struct diu __iomem *hw = machine_data->diu_reg; 533 struct diu __iomem *hw = data->diu_reg;
553 534
554 switch (mfbi->index) { 535 switch (mfbi->index) {
555 case PLANE0: 536 case PLANE0:
556 if (hw->desc[0] != machine_data->dummy_ad->paddr) 537 if (hw->desc[0] != data->dummy_ad.paddr)
557 wr_reg_wa(&hw->desc[0], machine_data->dummy_ad->paddr); 538 wr_reg_wa(&hw->desc[0], data->dummy_ad.paddr);
558 break; 539 break;
559 case PLANE1_AOI0: 540 case PLANE1_AOI0:
560 cmfbi = machine_data->fsl_diu_info[2]->par; 541 cmfbi = &data->mfb[2];
561 if (cmfbi->count > 0) /* AOI1 is open */ 542 if (cmfbi->count > 0) /* AOI1 is open */
562 wr_reg_wa(&hw->desc[1], cmfbi->ad->paddr); 543 wr_reg_wa(&hw->desc[1], cmfbi->ad->paddr);
563 /* move AOI1 to the first */ 544 /* move AOI1 to the first */
564 else /* AOI1 was closed */ 545 else /* AOI1 was closed */
565 wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr); 546 wr_reg_wa(&hw->desc[1], data->dummy_ad.paddr);
566 /* close AOI 0 */ 547 /* close AOI 0 */
567 break; 548 break;
568 case PLANE2_AOI0: 549 case PLANE2_AOI0:
569 cmfbi = machine_data->fsl_diu_info[4]->par; 550 cmfbi = &data->mfb[4];
570 if (cmfbi->count > 0) /* AOI1 is open */ 551 if (cmfbi->count > 0) /* AOI1 is open */
571 wr_reg_wa(&hw->desc[2], cmfbi->ad->paddr); 552 wr_reg_wa(&hw->desc[2], cmfbi->ad->paddr);
572 /* move AOI1 to the first */ 553 /* move AOI1 to the first */
573 else /* AOI1 was closed */ 554 else /* AOI1 was closed */
574 wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr); 555 wr_reg_wa(&hw->desc[2], data->dummy_ad.paddr);
575 /* close AOI 0 */ 556 /* close AOI 0 */
576 break; 557 break;
577 case PLANE1_AOI1: 558 case PLANE1_AOI1:
578 pmfbi = machine_data->fsl_diu_info[1]->par; 559 pmfbi = &data->mfb[1];
579 if (hw->desc[1] != ad->paddr) { 560 if (hw->desc[1] != ad->paddr) {
580 /* AOI1 is not the first in the chain */ 561 /* AOI1 is not the first in the chain */
581 if (pmfbi->count > 0) 562 if (pmfbi->count > 0)
582 /* AOI0 is open, must be the first */ 563 /* AOI0 is open, must be the first */
583 pmfbi->ad->next_ad = 0; 564 pmfbi->ad->next_ad = 0;
584 } else /* AOI1 is the first in the chain */ 565 } else /* AOI1 is the first in the chain */
585 wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr); 566 wr_reg_wa(&hw->desc[1], data->dummy_ad.paddr);
586 /* close AOI 1 */ 567 /* close AOI 1 */
587 break; 568 break;
588 case PLANE2_AOI1: 569 case PLANE2_AOI1:
589 pmfbi = machine_data->fsl_diu_info[3]->par; 570 pmfbi = &data->mfb[3];
590 if (hw->desc[2] != ad->paddr) { 571 if (hw->desc[2] != ad->paddr) {
591 /* AOI1 is not the first in the chain */ 572 /* AOI1 is not the first in the chain */
592 if (pmfbi->count > 0) 573 if (pmfbi->count > 0)
593 /* AOI0 is open, must be the first */ 574 /* AOI0 is open, must be the first */
594 pmfbi->ad->next_ad = 0; 575 pmfbi->ad->next_ad = 0;
595 } else /* AOI1 is the first in the chain */ 576 } else /* AOI1 is the first in the chain */
596 wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr); 577 wr_reg_wa(&hw->desc[2], data->dummy_ad.paddr);
597 /* close AOI 1 */ 578 /* close AOI 1 */
598 break; 579 break;
599 } 580 }
@@ -602,39 +583,33 @@ static void fsl_diu_disable_panel(struct fb_info *info)
602static void enable_lcdc(struct fb_info *info) 583static void enable_lcdc(struct fb_info *info)
603{ 584{
604 struct mfb_info *mfbi = info->par; 585 struct mfb_info *mfbi = info->par;
605 struct fsl_diu_data *machine_data = mfbi->parent; 586 struct fsl_diu_data *data = mfbi->parent;
606 struct diu __iomem *hw = machine_data->diu_reg; 587 struct diu __iomem *hw = data->diu_reg;
607 588
608 if (!machine_data->fb_enabled) { 589 out_be32(&hw->diu_mode, MFB_MODE1);
609 out_be32(&hw->diu_mode, MFB_MODE1);
610 machine_data->fb_enabled++;
611 }
612} 590}
613 591
614static void disable_lcdc(struct fb_info *info) 592static void disable_lcdc(struct fb_info *info)
615{ 593{
616 struct mfb_info *mfbi = info->par; 594 struct mfb_info *mfbi = info->par;
617 struct fsl_diu_data *machine_data = mfbi->parent; 595 struct fsl_diu_data *data = mfbi->parent;
618 struct diu __iomem *hw = machine_data->diu_reg; 596 struct diu __iomem *hw = data->diu_reg;
619 597
620 if (machine_data->fb_enabled) { 598 out_be32(&hw->diu_mode, 0);
621 out_be32(&hw->diu_mode, 0);
622 machine_data->fb_enabled = 0;
623 }
624} 599}
625 600
626static void adjust_aoi_size_position(struct fb_var_screeninfo *var, 601static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
627 struct fb_info *info) 602 struct fb_info *info)
628{ 603{
629 struct mfb_info *lower_aoi_mfbi, *upper_aoi_mfbi, *mfbi = info->par; 604 struct mfb_info *lower_aoi_mfbi, *upper_aoi_mfbi, *mfbi = info->par;
630 struct fsl_diu_data *machine_data = mfbi->parent; 605 struct fsl_diu_data *data = mfbi->parent;
631 int available_height, upper_aoi_bottom; 606 int available_height, upper_aoi_bottom;
632 enum mfb_index index = mfbi->index; 607 enum mfb_index index = mfbi->index;
633 int lower_aoi_is_open, upper_aoi_is_open; 608 int lower_aoi_is_open, upper_aoi_is_open;
634 __u32 base_plane_width, base_plane_height, upper_aoi_height; 609 __u32 base_plane_width, base_plane_height, upper_aoi_height;
635 610
636 base_plane_width = machine_data->fsl_diu_info[0]->var.xres; 611 base_plane_width = data->fsl_diu_info[0].var.xres;
637 base_plane_height = machine_data->fsl_diu_info[0]->var.yres; 612 base_plane_height = data->fsl_diu_info[0].var.yres;
638 613
639 if (mfbi->x_aoi_d < 0) 614 if (mfbi->x_aoi_d < 0)
640 mfbi->x_aoi_d = 0; 615 mfbi->x_aoi_d = 0;
@@ -649,7 +624,7 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
649 break; 624 break;
650 case PLANE1_AOI0: 625 case PLANE1_AOI0:
651 case PLANE2_AOI0: 626 case PLANE2_AOI0:
652 lower_aoi_mfbi = machine_data->fsl_diu_info[index+1]->par; 627 lower_aoi_mfbi = data->fsl_diu_info[index+1].par;
653 lower_aoi_is_open = lower_aoi_mfbi->count > 0 ? 1 : 0; 628 lower_aoi_is_open = lower_aoi_mfbi->count > 0 ? 1 : 0;
654 if (var->xres > base_plane_width) 629 if (var->xres > base_plane_width)
655 var->xres = base_plane_width; 630 var->xres = base_plane_width;
@@ -667,9 +642,8 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
667 break; 642 break;
668 case PLANE1_AOI1: 643 case PLANE1_AOI1:
669 case PLANE2_AOI1: 644 case PLANE2_AOI1:
670 upper_aoi_mfbi = machine_data->fsl_diu_info[index-1]->par; 645 upper_aoi_mfbi = data->fsl_diu_info[index-1].par;
671 upper_aoi_height = 646 upper_aoi_height = data->fsl_diu_info[index-1].var.yres;
672 machine_data->fsl_diu_info[index-1]->var.yres;
673 upper_aoi_bottom = upper_aoi_mfbi->y_aoi_d + upper_aoi_height; 647 upper_aoi_bottom = upper_aoi_mfbi->y_aoi_d + upper_aoi_height;
674 upper_aoi_is_open = upper_aoi_mfbi->count > 0 ? 1 : 0; 648 upper_aoi_is_open = upper_aoi_mfbi->count > 0 ? 1 : 0;
675 if (var->xres > base_plane_width) 649 if (var->xres > base_plane_width)
@@ -809,33 +783,33 @@ static void update_lcdc(struct fb_info *info)
809{ 783{
810 struct fb_var_screeninfo *var = &info->var; 784 struct fb_var_screeninfo *var = &info->var;
811 struct mfb_info *mfbi = info->par; 785 struct mfb_info *mfbi = info->par;
812 struct fsl_diu_data *machine_data = mfbi->parent; 786 struct fsl_diu_data *data = mfbi->parent;
813 struct diu __iomem *hw; 787 struct diu __iomem *hw;
814 int i, j; 788 int i, j;
815 char __iomem *cursor_base, *gamma_table_base; 789 u8 *gamma_table_base;
816 790
817 u32 temp; 791 u32 temp;
818 792
819 hw = machine_data->diu_reg; 793 hw = data->diu_reg;
794
795 diu_ops.set_monitor_port(data->monitor_port);
796 gamma_table_base = data->gamma;
820 797
821 diu_ops.set_monitor_port(machine_data->monitor_port);
822 gamma_table_base = machine_data->gamma.vaddr;
823 cursor_base = machine_data->cursor.vaddr;
824 /* Prep for DIU init - gamma table, cursor table */ 798 /* Prep for DIU init - gamma table, cursor table */
825 799
826 for (i = 0; i <= 2; i++) 800 for (i = 0; i <= 2; i++)
827 for (j = 0; j <= 255; j++) 801 for (j = 0; j <= 255; j++)
828 *gamma_table_base++ = j; 802 *gamma_table_base++ = j;
829 803
830 diu_ops.set_gamma_table(machine_data->monitor_port, 804 if (diu_ops.set_gamma_table)
831 machine_data->gamma.vaddr); 805 diu_ops.set_gamma_table(data->monitor_port, data->gamma);
832 806
833 disable_lcdc(info); 807 disable_lcdc(info);
834 808
835 /* Program DIU registers */ 809 /* Program DIU registers */
836 810
837 out_be32(&hw->gamma, machine_data->gamma.paddr); 811 out_be32(&hw->gamma, DMA_ADDR(data, gamma));
838 out_be32(&hw->cursor, machine_data->cursor.paddr); 812 out_be32(&hw->cursor, DMA_ADDR(data, cursor));
839 813
840 out_be32(&hw->bgnd, 0x007F7F7F); /* BGND */ 814 out_be32(&hw->bgnd, 0x007F7F7F); /* BGND */
841 out_be32(&hw->bgnd_wb, 0); /* BGND_WB */ 815 out_be32(&hw->bgnd_wb, 0); /* BGND_WB */
@@ -870,16 +844,17 @@ static void update_lcdc(struct fb_info *info)
870 844
871static int map_video_memory(struct fb_info *info) 845static int map_video_memory(struct fb_info *info)
872{ 846{
873 phys_addr_t phys;
874 u32 smem_len = info->fix.line_length * info->var.yres_virtual; 847 u32 smem_len = info->fix.line_length * info->var.yres_virtual;
848 void *p;
875 849
876 info->screen_base = fsl_diu_alloc(smem_len, &phys); 850 p = alloc_pages_exact(smem_len, GFP_DMA | __GFP_ZERO);
877 if (info->screen_base == NULL) { 851 if (!p) {
878 dev_err(info->dev, "unable to allocate fb memory\n"); 852 dev_err(info->dev, "unable to allocate fb memory\n");
879 return -ENOMEM; 853 return -ENOMEM;
880 } 854 }
881 mutex_lock(&info->mm_lock); 855 mutex_lock(&info->mm_lock);
882 info->fix.smem_start = (unsigned long) phys; 856 info->screen_base = p;
857 info->fix.smem_start = virt_to_phys(info->screen_base);
883 info->fix.smem_len = smem_len; 858 info->fix.smem_len = smem_len;
884 mutex_unlock(&info->mm_lock); 859 mutex_unlock(&info->mm_lock);
885 info->screen_size = info->fix.smem_len; 860 info->screen_size = info->fix.smem_len;
@@ -889,12 +864,17 @@ static int map_video_memory(struct fb_info *info)
889 864
890static void unmap_video_memory(struct fb_info *info) 865static void unmap_video_memory(struct fb_info *info)
891{ 866{
892 fsl_diu_free(info->screen_base, info->fix.smem_len); 867 void *p = info->screen_base;
868 size_t l = info->fix.smem_len;
869
893 mutex_lock(&info->mm_lock); 870 mutex_lock(&info->mm_lock);
894 info->screen_base = NULL; 871 info->screen_base = NULL;
895 info->fix.smem_start = 0; 872 info->fix.smem_start = 0;
896 info->fix.smem_len = 0; 873 info->fix.smem_len = 0;
897 mutex_unlock(&info->mm_lock); 874 mutex_unlock(&info->mm_lock);
875
876 if (p)
877 free_pages_exact(p, l);
898} 878}
899 879
900/* 880/*
@@ -913,6 +893,59 @@ static int fsl_diu_set_aoi(struct fb_info *info)
913 return 0; 893 return 0;
914} 894}
915 895
896/**
897 * fsl_diu_get_pixel_format: return the pixel format for a given color depth
898 *
899 * The pixel format is a 32-bit value that determine which bits in each
900 * pixel are to be used for each color. This is the default function used
901 * if the platform does not define its own version.
902 */
903static u32 fsl_diu_get_pixel_format(unsigned int bits_per_pixel)
904{
905#define PF_BYTE_F 0x10000000
906#define PF_ALPHA_C_MASK 0x0E000000
907#define PF_ALPHA_C_SHIFT 25
908#define PF_BLUE_C_MASK 0x01800000
909#define PF_BLUE_C_SHIFT 23
910#define PF_GREEN_C_MASK 0x00600000
911#define PF_GREEN_C_SHIFT 21
912#define PF_RED_C_MASK 0x00180000
913#define PF_RED_C_SHIFT 19
914#define PF_PALETTE 0x00040000
915#define PF_PIXEL_S_MASK 0x00030000
916#define PF_PIXEL_S_SHIFT 16
917#define PF_COMP_3_MASK 0x0000F000
918#define PF_COMP_3_SHIFT 12
919#define PF_COMP_2_MASK 0x00000F00
920#define PF_COMP_2_SHIFT 8
921#define PF_COMP_1_MASK 0x000000F0
922#define PF_COMP_1_SHIFT 4
923#define PF_COMP_0_MASK 0x0000000F
924#define PF_COMP_0_SHIFT 0
925
926#define MAKE_PF(alpha, red, blue, green, size, c0, c1, c2, c3) \
927 cpu_to_le32(PF_BYTE_F | (alpha << PF_ALPHA_C_SHIFT) | \
928 (blue << PF_BLUE_C_SHIFT) | (green << PF_GREEN_C_SHIFT) | \
929 (red << PF_RED_C_SHIFT) | (c3 << PF_COMP_3_SHIFT) | \
930 (c2 << PF_COMP_2_SHIFT) | (c1 << PF_COMP_1_SHIFT) | \
931 (c0 << PF_COMP_0_SHIFT) | (size << PF_PIXEL_S_SHIFT))
932
933 switch (bits_per_pixel) {
934 case 32:
935 /* 0x88883316 */
936 return MAKE_PF(3, 2, 0, 1, 3, 8, 8, 8, 8);
937 case 24:
938 /* 0x88082219 */
939 return MAKE_PF(4, 0, 1, 2, 2, 0, 8, 8, 8);
940 case 16:
941 /* 0x65053118 */
942 return MAKE_PF(4, 2, 1, 0, 1, 5, 6, 5, 0);
943 default:
944 pr_err("fsl-diu: unsupported color depth %u\n", bits_per_pixel);
945 return 0;
946 }
947}
948
916/* 949/*
917 * Using the fb_var_screeninfo in fb_info we set the resolution of this 950 * Using the fb_var_screeninfo in fb_info we set the resolution of this
918 * particular framebuffer. This function alters the fb_fix_screeninfo stored 951 * particular framebuffer. This function alters the fb_fix_screeninfo stored
@@ -926,11 +959,11 @@ static int fsl_diu_set_par(struct fb_info *info)
926 unsigned long len; 959 unsigned long len;
927 struct fb_var_screeninfo *var = &info->var; 960 struct fb_var_screeninfo *var = &info->var;
928 struct mfb_info *mfbi = info->par; 961 struct mfb_info *mfbi = info->par;
929 struct fsl_diu_data *machine_data = mfbi->parent; 962 struct fsl_diu_data *data = mfbi->parent;
930 struct diu_ad *ad = mfbi->ad; 963 struct diu_ad *ad = mfbi->ad;
931 struct diu __iomem *hw; 964 struct diu __iomem *hw;
932 965
933 hw = machine_data->diu_reg; 966 hw = data->diu_reg;
934 967
935 set_fix(info); 968 set_fix(info);
936 mfbi->cursor_reset = 1; 969 mfbi->cursor_reset = 1;
@@ -948,8 +981,12 @@ static int fsl_diu_set_par(struct fb_info *info)
948 } 981 }
949 } 982 }
950 983
951 ad->pix_fmt = diu_ops.get_pixel_format(machine_data->monitor_port, 984 if (diu_ops.get_pixel_format)
952 var->bits_per_pixel); 985 ad->pix_fmt = diu_ops.get_pixel_format(data->monitor_port,
986 var->bits_per_pixel);
987 else
988 ad->pix_fmt = fsl_diu_get_pixel_format(var->bits_per_pixel);
989
953 ad->addr = cpu_to_le32(info->fix.smem_start); 990 ad->addr = cpu_to_le32(info->fix.smem_start);
954 ad->src_size_g_alpha = cpu_to_le32((var->yres_virtual << 12) | 991 ad->src_size_g_alpha = cpu_to_le32((var->yres_virtual << 12) |
955 var->xres_virtual) | mfbi->g_alpha; 992 var->xres_virtual) | mfbi->g_alpha;
@@ -1208,21 +1245,6 @@ static struct fb_ops fsl_diu_ops = {
1208 .fb_release = fsl_diu_release, 1245 .fb_release = fsl_diu_release,
1209}; 1246};
1210 1247
1211static int init_fbinfo(struct fb_info *info)
1212{
1213 struct mfb_info *mfbi = info->par;
1214
1215 info->device = NULL;
1216 info->var.activate = FB_ACTIVATE_NOW;
1217 info->fbops = &fsl_diu_ops;
1218 info->flags = FBINFO_FLAG_DEFAULT;
1219 info->pseudo_palette = &mfbi->pseudo_palette;
1220
1221 /* Allocate colormap */
1222 fb_alloc_cmap(&info->cmap, 16, 0);
1223 return 0;
1224}
1225
1226static int __devinit install_fb(struct fb_info *info) 1248static int __devinit install_fb(struct fb_info *info)
1227{ 1249{
1228 int rc; 1250 int rc;
@@ -1232,8 +1254,15 @@ static int __devinit install_fb(struct fb_info *info)
1232 unsigned int dbsize = ARRAY_SIZE(fsl_diu_mode_db); 1254 unsigned int dbsize = ARRAY_SIZE(fsl_diu_mode_db);
1233 int has_default_mode = 1; 1255 int has_default_mode = 1;
1234 1256
1235 if (init_fbinfo(info)) 1257 info->var.activate = FB_ACTIVATE_NOW;
1236 return -EINVAL; 1258 info->fbops = &fsl_diu_ops;
1259 info->flags = FBINFO_DEFAULT | FBINFO_VIRTFB | FBINFO_PARTIAL_PAN_OK |
1260 FBINFO_READS_FAST;
1261 info->pseudo_palette = mfbi->pseudo_palette;
1262
1263 rc = fb_alloc_cmap(&info->cmap, 16, 0);
1264 if (rc)
1265 return rc;
1237 1266
1238 if (mfbi->index == PLANE0) { 1267 if (mfbi->index == PLANE0) {
1239 if (mfbi->edid_data) { 1268 if (mfbi->edid_data) {
@@ -1359,16 +1388,16 @@ static irqreturn_t fsl_diu_isr(int irq, void *dev_id)
1359 return IRQ_NONE; 1388 return IRQ_NONE;
1360} 1389}
1361 1390
1362static int request_irq_local(struct fsl_diu_data *machine_data) 1391static int request_irq_local(struct fsl_diu_data *data)
1363{ 1392{
1364 struct diu __iomem *hw = machine_data->diu_reg; 1393 struct diu __iomem *hw = data->diu_reg;
1365 u32 ints; 1394 u32 ints;
1366 int ret; 1395 int ret;
1367 1396
1368 /* Read to clear the status */ 1397 /* Read to clear the status */
1369 in_be32(&hw->int_status); 1398 in_be32(&hw->int_status);
1370 1399
1371 ret = request_irq(machine_data->irq, fsl_diu_isr, 0, "fsl-diu-fb", hw); 1400 ret = request_irq(data->irq, fsl_diu_isr, 0, "fsl-diu-fb", hw);
1372 if (!ret) { 1401 if (!ret) {
1373 ints = INT_PARERR | INT_LS_BF_VS; 1402 ints = INT_PARERR | INT_LS_BF_VS;
1374#if !defined(CONFIG_NOT_COHERENT_CACHE) 1403#if !defined(CONFIG_NOT_COHERENT_CACHE)
@@ -1383,14 +1412,14 @@ static int request_irq_local(struct fsl_diu_data *machine_data)
1383 return ret; 1412 return ret;
1384} 1413}
1385 1414
1386static void free_irq_local(struct fsl_diu_data *machine_data) 1415static void free_irq_local(struct fsl_diu_data *data)
1387{ 1416{
1388 struct diu __iomem *hw = machine_data->diu_reg; 1417 struct diu __iomem *hw = data->diu_reg;
1389 1418
1390 /* Disable all LCDC interrupt */ 1419 /* Disable all LCDC interrupt */
1391 out_be32(&hw->int_mask, 0x1f); 1420 out_be32(&hw->int_mask, 0x1f);
1392 1421
1393 free_irq(machine_data->irq, NULL); 1422 free_irq(data->irq, NULL);
1394} 1423}
1395 1424
1396#ifdef CONFIG_PM 1425#ifdef CONFIG_PM
@@ -1400,20 +1429,20 @@ static void free_irq_local(struct fsl_diu_data *machine_data)
1400 */ 1429 */
1401static int fsl_diu_suspend(struct platform_device *ofdev, pm_message_t state) 1430static int fsl_diu_suspend(struct platform_device *ofdev, pm_message_t state)
1402{ 1431{
1403 struct fsl_diu_data *machine_data; 1432 struct fsl_diu_data *data;
1404 1433
1405 machine_data = dev_get_drvdata(&ofdev->dev); 1434 data = dev_get_drvdata(&ofdev->dev);
1406 disable_lcdc(machine_data->fsl_diu_info[0]); 1435 disable_lcdc(data->fsl_diu_info[0]);
1407 1436
1408 return 0; 1437 return 0;
1409} 1438}
1410 1439
1411static int fsl_diu_resume(struct platform_device *ofdev) 1440static int fsl_diu_resume(struct platform_device *ofdev)
1412{ 1441{
1413 struct fsl_diu_data *machine_data; 1442 struct fsl_diu_data *data;
1414 1443
1415 machine_data = dev_get_drvdata(&ofdev->dev); 1444 data = dev_get_drvdata(&ofdev->dev);
1416 enable_lcdc(machine_data->fsl_diu_info[0]); 1445 enable_lcdc(data->fsl_diu_info[0]);
1417 1446
1418 return 0; 1447 return 0;
1419} 1448}
@@ -1423,56 +1452,24 @@ static int fsl_diu_resume(struct platform_device *ofdev)
1423#define fsl_diu_resume NULL 1452#define fsl_diu_resume NULL
1424#endif /* CONFIG_PM */ 1453#endif /* CONFIG_PM */
1425 1454
1426/* Align to 64-bit(8-byte), 32-byte, etc. */
1427static int allocate_buf(struct device *dev, struct diu_addr *buf, u32 size,
1428 u32 bytes_align)
1429{
1430 u32 offset;
1431 dma_addr_t mask;
1432
1433 buf->vaddr =
1434 dma_alloc_coherent(dev, size + bytes_align, &buf->paddr,
1435 GFP_DMA | __GFP_ZERO);
1436 if (!buf->vaddr)
1437 return -ENOMEM;
1438
1439 mask = bytes_align - 1;
1440 offset = buf->paddr & mask;
1441 if (offset) {
1442 buf->offset = bytes_align - offset;
1443 buf->paddr = buf->paddr + offset;
1444 } else
1445 buf->offset = 0;
1446
1447 return 0;
1448}
1449
1450static void free_buf(struct device *dev, struct diu_addr *buf, u32 size,
1451 u32 bytes_align)
1452{
1453 dma_free_coherent(dev, size + bytes_align, buf->vaddr,
1454 buf->paddr - buf->offset);
1455}
1456
1457static ssize_t store_monitor(struct device *device, 1455static ssize_t store_monitor(struct device *device,
1458 struct device_attribute *attr, const char *buf, size_t count) 1456 struct device_attribute *attr, const char *buf, size_t count)
1459{ 1457{
1460 enum fsl_diu_monitor_port old_monitor_port; 1458 enum fsl_diu_monitor_port old_monitor_port;
1461 struct fsl_diu_data *machine_data = 1459 struct fsl_diu_data *data =
1462 container_of(attr, struct fsl_diu_data, dev_attr); 1460 container_of(attr, struct fsl_diu_data, dev_attr);
1463 1461
1464 old_monitor_port = machine_data->monitor_port; 1462 old_monitor_port = data->monitor_port;
1465 machine_data->monitor_port = fsl_diu_name_to_port(buf); 1463 data->monitor_port = fsl_diu_name_to_port(buf);
1466 1464
1467 if (old_monitor_port != machine_data->monitor_port) { 1465 if (old_monitor_port != data->monitor_port) {
1468 /* All AOIs need adjust pixel format 1466 /* All AOIs need adjust pixel format
1469 * fsl_diu_set_par only change the pixsel format here 1467 * fsl_diu_set_par only change the pixsel format here
1470 * unlikely to fail. */ 1468 * unlikely to fail. */
1471 fsl_diu_set_par(machine_data->fsl_diu_info[0]); 1469 unsigned int i;
1472 fsl_diu_set_par(machine_data->fsl_diu_info[1]); 1470
1473 fsl_diu_set_par(machine_data->fsl_diu_info[2]); 1471 for (i=0; i < NUM_AOIS; i++)
1474 fsl_diu_set_par(machine_data->fsl_diu_info[3]); 1472 fsl_diu_set_par(&data->fsl_diu_info[i]);
1475 fsl_diu_set_par(machine_data->fsl_diu_info[4]);
1476 } 1473 }
1477 return count; 1474 return count;
1478} 1475}
@@ -1480,10 +1477,10 @@ static ssize_t store_monitor(struct device *device,
1480static ssize_t show_monitor(struct device *device, 1477static ssize_t show_monitor(struct device *device,
1481 struct device_attribute *attr, char *buf) 1478 struct device_attribute *attr, char *buf)
1482{ 1479{
1483 struct fsl_diu_data *machine_data = 1480 struct fsl_diu_data *data =
1484 container_of(attr, struct fsl_diu_data, dev_attr); 1481 container_of(attr, struct fsl_diu_data, dev_attr);
1485 1482
1486 switch (machine_data->monitor_port) { 1483 switch (data->monitor_port) {
1487 case FSL_DIU_PORT_DVI: 1484 case FSL_DIU_PORT_DVI:
1488 return sprintf(buf, "DVI\n"); 1485 return sprintf(buf, "DVI\n");
1489 case FSL_DIU_PORT_LVDS: 1486 case FSL_DIU_PORT_LVDS:
@@ -1499,28 +1496,52 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
1499{ 1496{
1500 struct device_node *np = pdev->dev.of_node; 1497 struct device_node *np = pdev->dev.of_node;
1501 struct mfb_info *mfbi; 1498 struct mfb_info *mfbi;
1502 phys_addr_t dummy_ad_addr = 0; 1499 struct fsl_diu_data *data;
1503 int ret, i, error = 0;
1504 struct fsl_diu_data *machine_data;
1505 int diu_mode; 1500 int diu_mode;
1501 dma_addr_t dma_addr; /* DMA addr of fsl_diu_data struct */
1502 unsigned int i;
1503 int ret;
1506 1504
1507 machine_data = kzalloc(sizeof(struct fsl_diu_data), GFP_KERNEL); 1505 data = dma_alloc_coherent(&pdev->dev, sizeof(struct fsl_diu_data),
1508 if (!machine_data) 1506 &dma_addr, GFP_DMA | __GFP_ZERO);
1507 if (!data)
1509 return -ENOMEM; 1508 return -ENOMEM;
1509 data->dma_addr = dma_addr;
1510
1511 /*
1512 * dma_alloc_coherent() uses a page allocator, so the address is
1513 * always page-aligned. We need the memory to be 32-byte aligned,
1514 * so that's good. However, if one day the allocator changes, we
1515 * need to catch that. It's not worth the effort to handle unaligned
1516 * alloctions now because it's highly unlikely to ever be a problem.
1517 */
1518 if ((unsigned long)data & 31) {
1519 dev_err(&pdev->dev, "misaligned allocation");
1520 ret = -ENOMEM;
1521 goto error;
1522 }
1510 1523
1511 spin_lock_init(&machine_data->reg_lock); 1524 spin_lock_init(&data->reg_lock);
1512 1525
1513 for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) { 1526 for (i = 0; i < NUM_AOIS; i++) {
1514 machine_data->fsl_diu_info[i] = 1527 struct fb_info *info = &data->fsl_diu_info[i];
1515 framebuffer_alloc(sizeof(struct mfb_info), &pdev->dev); 1528
1516 if (!machine_data->fsl_diu_info[i]) { 1529 info->device = &pdev->dev;
1517 dev_err(&pdev->dev, "cannot allocate memory\n"); 1530 info->par = &data->mfb[i];
1518 ret = -ENOMEM; 1531
1519 goto error2; 1532 /*
1520 } 1533 * We store the physical address of the AD in the reserved
1521 mfbi = machine_data->fsl_diu_info[i]->par; 1534 * 'paddr' field of the AD itself.
1535 */
1536 data->ad[i].paddr = DMA_ADDR(data, ad[i]);
1537
1538 info->fix.smem_start = 0;
1539
1540 /* Initialize the AOI data structure */
1541 mfbi = info->par;
1522 memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info)); 1542 memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info));
1523 mfbi->parent = machine_data; 1543 mfbi->parent = data;
1544 mfbi->ad = &data->ad[i];
1524 1545
1525 if (mfbi->index == PLANE0) { 1546 if (mfbi->index == PLANE0) {
1526 const u8 *prop; 1547 const u8 *prop;
@@ -1534,158 +1555,102 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
1534 } 1555 }
1535 } 1556 }
1536 1557
1537 machine_data->diu_reg = of_iomap(np, 0); 1558 data->diu_reg = of_iomap(np, 0);
1538 if (!machine_data->diu_reg) { 1559 if (!data->diu_reg) {
1539 dev_err(&pdev->dev, "cannot map DIU registers\n"); 1560 dev_err(&pdev->dev, "cannot map DIU registers\n");
1540 ret = -EFAULT; 1561 ret = -EFAULT;
1541 goto error2; 1562 goto error;
1542 } 1563 }
1543 1564
1544 diu_mode = in_be32(&machine_data->diu_reg->diu_mode); 1565 diu_mode = in_be32(&data->diu_reg->diu_mode);
1545 if (diu_mode == MFB_MODE0) 1566 if (diu_mode == MFB_MODE0)
1546 out_be32(&machine_data->diu_reg->diu_mode, 0); /* disable DIU */ 1567 out_be32(&data->diu_reg->diu_mode, 0); /* disable DIU */
1547 1568
1548 /* Get the IRQ of the DIU */ 1569 /* Get the IRQ of the DIU */
1549 machine_data->irq = irq_of_parse_and_map(np, 0); 1570 data->irq = irq_of_parse_and_map(np, 0);
1550 1571
1551 if (!machine_data->irq) { 1572 if (!data->irq) {
1552 dev_err(&pdev->dev, "could not get DIU IRQ\n"); 1573 dev_err(&pdev->dev, "could not get DIU IRQ\n");
1553 ret = -EINVAL; 1574 ret = -EINVAL;
1554 goto error; 1575 goto error;
1555 } 1576 }
1556 machine_data->monitor_port = monitor_port; 1577 data->monitor_port = monitor_port;
1557 1578
1558 /* Area descriptor memory pool aligns to 64-bit boundary */ 1579 /* Initialize the dummy Area Descriptor */
1559 if (allocate_buf(&pdev->dev, &machine_data->ad, 1580 data->dummy_ad.addr = cpu_to_le32(DMA_ADDR(data, dummy_aoi));
1560 sizeof(struct diu_ad) * FSL_AOI_NUM, 8)) 1581 data->dummy_ad.pix_fmt = 0x88882317;
1561 return -ENOMEM; 1582 data->dummy_ad.src_size_g_alpha = cpu_to_le32((4 << 12) | 4);
1562 1583 data->dummy_ad.aoi_size = cpu_to_le32((4 << 16) | 2);
1563 /* Get memory for Gamma Table - 32-byte aligned memory */ 1584 data->dummy_ad.offset_xyi = 0;
1564 if (allocate_buf(&pdev->dev, &machine_data->gamma, 768, 32)) { 1585 data->dummy_ad.offset_xyd = 0;
1565 ret = -ENOMEM; 1586 data->dummy_ad.next_ad = 0;
1566 goto error; 1587 data->dummy_ad.paddr = DMA_ADDR(data, dummy_ad);
1567 }
1568
1569 /* For performance, cursor bitmap buffer aligns to 32-byte boundary */
1570 if (allocate_buf(&pdev->dev, &machine_data->cursor,
1571 MAX_CURS * MAX_CURS * 2, 32)) {
1572 ret = -ENOMEM;
1573 goto error;
1574 }
1575
1576 i = ARRAY_SIZE(machine_data->fsl_diu_info);
1577 machine_data->dummy_ad = (struct diu_ad *)((u32)machine_data->ad.vaddr +
1578 machine_data->ad.offset) + i;
1579 machine_data->dummy_ad->paddr = machine_data->ad.paddr +
1580 i * sizeof(struct diu_ad);
1581 machine_data->dummy_aoi_virt = fsl_diu_alloc(64, &dummy_ad_addr);
1582 if (!machine_data->dummy_aoi_virt) {
1583 ret = -ENOMEM;
1584 goto error;
1585 }
1586 machine_data->dummy_ad->addr = cpu_to_le32(dummy_ad_addr);
1587 machine_data->dummy_ad->pix_fmt = 0x88882317;
1588 machine_data->dummy_ad->src_size_g_alpha = cpu_to_le32((4 << 12) | 4);
1589 machine_data->dummy_ad->aoi_size = cpu_to_le32((4 << 16) | 2);
1590 machine_data->dummy_ad->offset_xyi = 0;
1591 machine_data->dummy_ad->offset_xyd = 0;
1592 machine_data->dummy_ad->next_ad = 0;
1593 1588
1594 /* 1589 /*
1595 * Let DIU display splash screen if it was pre-initialized 1590 * Let DIU display splash screen if it was pre-initialized
1596 * by the bootloader, set dummy area descriptor otherwise. 1591 * by the bootloader, set dummy area descriptor otherwise.
1597 */ 1592 */
1598 if (diu_mode == MFB_MODE0) 1593 if (diu_mode == MFB_MODE0)
1599 out_be32(&machine_data->diu_reg->desc[0], 1594 out_be32(&data->diu_reg->desc[0], data->dummy_ad.paddr);
1600 machine_data->dummy_ad->paddr); 1595
1601 1596 out_be32(&data->diu_reg->desc[1], data->dummy_ad.paddr);
1602 out_be32(&machine_data->diu_reg->desc[1], machine_data->dummy_ad->paddr); 1597 out_be32(&data->diu_reg->desc[2], data->dummy_ad.paddr);
1603 out_be32(&machine_data->diu_reg->desc[2], machine_data->dummy_ad->paddr); 1598
1604 1599 for (i = 0; i < NUM_AOIS; i++) {
1605 for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) { 1600 ret = install_fb(&data->fsl_diu_info[i]);
1606 machine_data->fsl_diu_info[i]->fix.smem_start = 0;
1607 mfbi = machine_data->fsl_diu_info[i]->par;
1608 mfbi->ad = (struct diu_ad *)((u32)machine_data->ad.vaddr
1609 + machine_data->ad.offset) + i;
1610 mfbi->ad->paddr =
1611 machine_data->ad.paddr + i * sizeof(struct diu_ad);
1612 ret = install_fb(machine_data->fsl_diu_info[i]);
1613 if (ret) { 1601 if (ret) {
1614 dev_err(&pdev->dev, "could not register fb %d\n", i); 1602 dev_err(&pdev->dev, "could not register fb %d\n", i);
1615 goto error; 1603 goto error;
1616 } 1604 }
1617 } 1605 }
1618 1606
1619 if (request_irq_local(machine_data)) { 1607 if (request_irq_local(data)) {
1620 dev_err(&pdev->dev, "could not claim irq\n"); 1608 dev_err(&pdev->dev, "could not claim irq\n");
1621 goto error; 1609 goto error;
1622 } 1610 }
1623 1611
1624 sysfs_attr_init(&machine_data->dev_attr.attr); 1612 sysfs_attr_init(&data->dev_attr.attr);
1625 machine_data->dev_attr.attr.name = "monitor"; 1613 data->dev_attr.attr.name = "monitor";
1626 machine_data->dev_attr.attr.mode = S_IRUGO|S_IWUSR; 1614 data->dev_attr.attr.mode = S_IRUGO|S_IWUSR;
1627 machine_data->dev_attr.show = show_monitor; 1615 data->dev_attr.show = show_monitor;
1628 machine_data->dev_attr.store = store_monitor; 1616 data->dev_attr.store = store_monitor;
1629 error = device_create_file(machine_data->fsl_diu_info[0]->dev, 1617 ret = device_create_file(&pdev->dev, &data->dev_attr);
1630 &machine_data->dev_attr); 1618 if (ret) {
1631 if (error) {
1632 dev_err(&pdev->dev, "could not create sysfs file %s\n", 1619 dev_err(&pdev->dev, "could not create sysfs file %s\n",
1633 machine_data->dev_attr.attr.name); 1620 data->dev_attr.attr.name);
1634 } 1621 }
1635 1622
1636 dev_set_drvdata(&pdev->dev, machine_data); 1623 dev_set_drvdata(&pdev->dev, data);
1637 return 0; 1624 return 0;
1638 1625
1639error: 1626error:
1640 for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) 1627 for (i = 0; i < NUM_AOIS; i++)
1641 uninstall_fb(machine_data->fsl_diu_info[i]); 1628 uninstall_fb(&data->fsl_diu_info[i]);
1642 1629
1643 if (machine_data->ad.vaddr) 1630 iounmap(data->diu_reg);
1644 free_buf(&pdev->dev, &machine_data->ad, 1631
1645 sizeof(struct diu_ad) * FSL_AOI_NUM, 8); 1632 dma_free_coherent(&pdev->dev, sizeof(struct fsl_diu_data), data,
1646 if (machine_data->gamma.vaddr) 1633 data->dma_addr);
1647 free_buf(&pdev->dev, &machine_data->gamma, 768, 32);
1648 if (machine_data->cursor.vaddr)
1649 free_buf(&pdev->dev, &machine_data->cursor,
1650 MAX_CURS * MAX_CURS * 2, 32);
1651 if (machine_data->dummy_aoi_virt)
1652 fsl_diu_free(machine_data->dummy_aoi_virt, 64);
1653 iounmap(machine_data->diu_reg);
1654
1655error2:
1656 for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++)
1657 if (machine_data->fsl_diu_info[i])
1658 framebuffer_release(machine_data->fsl_diu_info[i]);
1659 kfree(machine_data);
1660 1634
1661 return ret; 1635 return ret;
1662} 1636}
1663 1637
1664static int fsl_diu_remove(struct platform_device *pdev) 1638static int fsl_diu_remove(struct platform_device *pdev)
1665{ 1639{
1666 struct fsl_diu_data *machine_data; 1640 struct fsl_diu_data *data;
1667 int i; 1641 int i;
1668 1642
1669 machine_data = dev_get_drvdata(&pdev->dev); 1643 data = dev_get_drvdata(&pdev->dev);
1670 disable_lcdc(machine_data->fsl_diu_info[0]); 1644 disable_lcdc(&data->fsl_diu_info[0]);
1671 free_irq_local(machine_data); 1645 free_irq_local(data);
1672 for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) 1646
1673 uninstall_fb(machine_data->fsl_diu_info[i]); 1647 for (i = 0; i < NUM_AOIS; i++)
1674 if (machine_data->ad.vaddr) 1648 uninstall_fb(&data->fsl_diu_info[i]);
1675 free_buf(&pdev->dev, &machine_data->ad, 1649
1676 sizeof(struct diu_ad) * FSL_AOI_NUM, 8); 1650 iounmap(data->diu_reg);
1677 if (machine_data->gamma.vaddr) 1651
1678 free_buf(&pdev->dev, &machine_data->gamma, 768, 32); 1652 dma_free_coherent(&pdev->dev, sizeof(struct fsl_diu_data), data,
1679 if (machine_data->cursor.vaddr) 1653 data->dma_addr);
1680 free_buf(&pdev->dev, &machine_data->cursor,
1681 MAX_CURS * MAX_CURS * 2, 32);
1682 if (machine_data->dummy_aoi_virt)
1683 fsl_diu_free(machine_data->dummy_aoi_virt, 64);
1684 iounmap(machine_data->diu_reg);
1685 for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++)
1686 if (machine_data->fsl_diu_info[i])
1687 framebuffer_release(machine_data->fsl_diu_info[i]);
1688 kfree(machine_data);
1689 1654
1690 return 0; 1655 return 0;
1691} 1656}
diff --git a/drivers/video/grvga.c b/drivers/video/grvga.c
index f37e02538203..da066c210923 100644
--- a/drivers/video/grvga.c
+++ b/drivers/video/grvga.c
@@ -70,7 +70,7 @@ static const struct fb_videomode grvga_modedb[] = {
70 } 70 }
71 }; 71 };
72 72
73static struct fb_fix_screeninfo grvga_fix __initdata = { 73static struct fb_fix_screeninfo grvga_fix __devinitdata = {
74 .id = "AG SVGACTRL", 74 .id = "AG SVGACTRL",
75 .type = FB_TYPE_PACKED_PIXELS, 75 .type = FB_TYPE_PACKED_PIXELS,
76 .visual = FB_VISUAL_PSEUDOCOLOR, 76 .visual = FB_VISUAL_PSEUDOCOLOR,
@@ -267,7 +267,7 @@ static struct fb_ops grvga_ops = {
267 .fb_imageblit = cfb_imageblit 267 .fb_imageblit = cfb_imageblit
268}; 268};
269 269
270static int __init grvga_parse_custom(char *options, 270static int __devinit grvga_parse_custom(char *options,
271 struct fb_var_screeninfo *screendata) 271 struct fb_var_screeninfo *screendata)
272{ 272{
273 char *this_opt; 273 char *this_opt;
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index 318f6fb895b2..b83f36190cae 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -135,8 +135,8 @@ static struct pci_driver i810fb_driver = {
135static char *mode_option __devinitdata = NULL; 135static char *mode_option __devinitdata = NULL;
136static int vram __devinitdata = 4; 136static int vram __devinitdata = 4;
137static int bpp __devinitdata = 8; 137static int bpp __devinitdata = 8;
138static int mtrr __devinitdata; 138static bool mtrr __devinitdata;
139static int accel __devinitdata; 139static bool accel __devinitdata;
140static int hsync1 __devinitdata; 140static int hsync1 __devinitdata;
141static int hsync2 __devinitdata; 141static int hsync2 __devinitdata;
142static int vsync1 __devinitdata; 142static int vsync1 __devinitdata;
@@ -144,10 +144,10 @@ static int vsync2 __devinitdata;
144static int xres __devinitdata; 144static int xres __devinitdata;
145static int yres; 145static int yres;
146static int vyres __devinitdata; 146static int vyres __devinitdata;
147static int sync __devinitdata; 147static bool sync __devinitdata;
148static int extvga __devinitdata; 148static bool extvga __devinitdata;
149static int dcolor __devinitdata; 149static bool dcolor __devinitdata;
150static int ddc3 __devinitdata = 2; 150static bool ddc3 __devinitdata;
151 151
152/*------------------------------------------------------------*/ 152/*------------------------------------------------------------*/
153 153
@@ -1776,7 +1776,7 @@ static void __devinit i810_init_defaults(struct i810fb_par *par,
1776 if (sync) 1776 if (sync)
1777 par->dev_flags |= ALWAYS_SYNC; 1777 par->dev_flags |= ALWAYS_SYNC;
1778 1778
1779 par->ddc_num = ddc3; 1779 par->ddc_num = (ddc3 ? 3 : 2);
1780 1780
1781 if (bpp < 8) 1781 if (bpp < 8)
1782 bpp = 8; 1782 bpp = 8;
@@ -1999,7 +1999,7 @@ static int __devinit i810fb_setup(char *options)
1999 else if (!strncmp(this_opt, "dcolor", 6)) 1999 else if (!strncmp(this_opt, "dcolor", 6))
2000 dcolor = 1; 2000 dcolor = 1;
2001 else if (!strncmp(this_opt, "ddc3", 4)) 2001 else if (!strncmp(this_opt, "ddc3", 4))
2002 ddc3 = 3; 2002 ddc3 = true;
2003 else 2003 else
2004 mode_option = this_opt; 2004 mode_option = this_opt;
2005 } 2005 }
diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c
index 44bf8d4a216b..401a56e250bd 100644
--- a/drivers/video/matrox/matroxfb_base.c
+++ b/drivers/video/matrox/matroxfb_base.c
@@ -147,7 +147,6 @@ static struct fb_var_screeninfo vesafb_defined = {
147 39721L,48L,16L,33L,10L, 147 39721L,48L,16L,33L,10L,
148 96L,2L,~0, /* No sync info */ 148 96L,2L,~0, /* No sync info */
149 FB_VMODE_NONINTERLACED, 149 FB_VMODE_NONINTERLACED,
150 0, {0,0,0,0,0}
151}; 150};
152 151
153 152
diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c
index d7112c39614b..02796a4317a9 100644
--- a/drivers/video/matrox/matroxfb_crtc2.c
+++ b/drivers/video/matrox/matroxfb_crtc2.c
@@ -593,7 +593,6 @@ static struct fb_var_screeninfo matroxfb_dh_defined = {
593 39721L,48L,16L,33L,10L, 593 39721L,48L,16L,33L,10L,
594 96L,2,0, /* no sync info */ 594 96L,2,0, /* no sync info */
595 FB_VMODE_NONINTERLACED, 595 FB_VMODE_NONINTERLACED,
596 0, {0,0,0,0,0}
597}; 596};
598 597
599static int matroxfb_dh_regit(const struct matrox_fb_info *minfo, 598static int matroxfb_dh_regit(const struct matrox_fb_info *minfo,
diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/mbx/mbxfb.c
index 6ce34160da78..55bf6196b7a0 100644
--- a/drivers/video/mbx/mbxfb.c
+++ b/drivers/video/mbx/mbxfb.c
@@ -1053,18 +1053,7 @@ static struct platform_driver mbxfb_driver = {
1053 }, 1053 },
1054}; 1054};
1055 1055
1056int __devinit mbxfb_init(void) 1056module_platform_driver(mbxfb_driver);
1057{
1058 return platform_driver_register(&mbxfb_driver);
1059}
1060
1061static void __devexit mbxfb_exit(void)
1062{
1063 platform_driver_unregister(&mbxfb_driver);
1064}
1065
1066module_init(mbxfb_init);
1067module_exit(mbxfb_exit);
1068 1057
1069MODULE_DESCRIPTION("loadable framebuffer driver for Marathon device"); 1058MODULE_DESCRIPTION("loadable framebuffer driver for Marathon device");
1070MODULE_AUTHOR("Mike Rapoport, Compulab"); 1059MODULE_AUTHOR("Mike Rapoport, Compulab");
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c
index eb3c5eea1a0f..4a89f889852d 100644
--- a/drivers/video/mxsfb.c
+++ b/drivers/video/mxsfb.c
@@ -902,18 +902,7 @@ static struct platform_driver mxsfb_driver = {
902 }, 902 },
903}; 903};
904 904
905static int __init mxsfb_init(void) 905module_platform_driver(mxsfb_driver);
906{
907 return platform_driver_register(&mxsfb_driver);
908}
909
910static void __exit mxsfb_exit(void)
911{
912 platform_driver_unregister(&mxsfb_driver);
913}
914
915module_init(mxsfb_init);
916module_exit(mxsfb_exit);
917 906
918MODULE_DESCRIPTION("Freescale mxs framebuffer driver"); 907MODULE_DESCRIPTION("Freescale mxs framebuffer driver");
919MODULE_AUTHOR("Sascha Hauer, Pengutronix"); 908MODULE_AUTHOR("Sascha Hauer, Pengutronix");
diff --git a/drivers/video/nuc900fb.c b/drivers/video/nuc900fb.c
index d1fbbd888cf4..e10f551ade21 100644
--- a/drivers/video/nuc900fb.c
+++ b/drivers/video/nuc900fb.c
@@ -762,18 +762,7 @@ static struct platform_driver nuc900fb_driver = {
762 }, 762 },
763}; 763};
764 764
765int __devinit nuc900fb_init(void) 765module_platform_driver(nuc900fb_driver);
766{
767 return platform_driver_register(&nuc900fb_driver);
768}
769
770static void __exit nuc900fb_cleanup(void)
771{
772 platform_driver_unregister(&nuc900fb_driver);
773}
774
775module_init(nuc900fb_init);
776module_exit(nuc900fb_cleanup);
777 766
778MODULE_DESCRIPTION("Framebuffer driver for the NUC900"); 767MODULE_DESCRIPTION("Framebuffer driver for the NUC900");
779MODULE_LICENSE("GPL"); 768MODULE_LICENSE("GPL");
diff --git a/drivers/video/omap/lcd_ams_delta.c b/drivers/video/omap/lcd_ams_delta.c
index 6978ae4ef83a..0fdd6f6873bf 100644
--- a/drivers/video/omap/lcd_ams_delta.c
+++ b/drivers/video/omap/lcd_ams_delta.c
@@ -198,7 +198,7 @@ static int ams_delta_panel_resume(struct platform_device *pdev)
198 return 0; 198 return 0;
199} 199}
200 200
201struct platform_driver ams_delta_panel_driver = { 201static struct platform_driver ams_delta_panel_driver = {
202 .probe = ams_delta_panel_probe, 202 .probe = ams_delta_panel_probe,
203 .remove = ams_delta_panel_remove, 203 .remove = ams_delta_panel_remove,
204 .suspend = ams_delta_panel_suspend, 204 .suspend = ams_delta_panel_suspend,
@@ -209,15 +209,4 @@ struct platform_driver ams_delta_panel_driver = {
209 }, 209 },
210}; 210};
211 211
212static int __init ams_delta_panel_drv_init(void) 212module_platform_driver(ams_delta_panel_driver);
213{
214 return platform_driver_register(&ams_delta_panel_driver);
215}
216
217static void __exit ams_delta_panel_drv_cleanup(void)
218{
219 platform_driver_unregister(&ams_delta_panel_driver);
220}
221
222module_init(ams_delta_panel_drv_init);
223module_exit(ams_delta_panel_drv_cleanup);
diff --git a/drivers/video/omap/lcd_h3.c b/drivers/video/omap/lcd_h3.c
index 622ad839fd9d..49bdeca81e50 100644
--- a/drivers/video/omap/lcd_h3.c
+++ b/drivers/video/omap/lcd_h3.c
@@ -113,7 +113,7 @@ static int h3_panel_resume(struct platform_device *pdev)
113 return 0; 113 return 0;
114} 114}
115 115
116struct platform_driver h3_panel_driver = { 116static struct platform_driver h3_panel_driver = {
117 .probe = h3_panel_probe, 117 .probe = h3_panel_probe,
118 .remove = h3_panel_remove, 118 .remove = h3_panel_remove,
119 .suspend = h3_panel_suspend, 119 .suspend = h3_panel_suspend,
@@ -124,16 +124,4 @@ struct platform_driver h3_panel_driver = {
124 }, 124 },
125}; 125};
126 126
127static int __init h3_panel_drv_init(void) 127module_platform_driver(h3_panel_driver);
128{
129 return platform_driver_register(&h3_panel_driver);
130}
131
132static void __exit h3_panel_drv_cleanup(void)
133{
134 platform_driver_unregister(&h3_panel_driver);
135}
136
137module_init(h3_panel_drv_init);
138module_exit(h3_panel_drv_cleanup);
139
diff --git a/drivers/video/omap/lcd_htcherald.c b/drivers/video/omap/lcd_htcherald.c
index 4802419da83b..20f477851d54 100644
--- a/drivers/video/omap/lcd_htcherald.c
+++ b/drivers/video/omap/lcd_htcherald.c
@@ -104,7 +104,7 @@ static int htcherald_panel_resume(struct platform_device *pdev)
104 return 0; 104 return 0;
105} 105}
106 106
107struct platform_driver htcherald_panel_driver = { 107static struct platform_driver htcherald_panel_driver = {
108 .probe = htcherald_panel_probe, 108 .probe = htcherald_panel_probe,
109 .remove = htcherald_panel_remove, 109 .remove = htcherald_panel_remove,
110 .suspend = htcherald_panel_suspend, 110 .suspend = htcherald_panel_suspend,
@@ -115,16 +115,4 @@ struct platform_driver htcherald_panel_driver = {
115 }, 115 },
116}; 116};
117 117
118static int __init htcherald_panel_drv_init(void) 118module_platform_driver(htcherald_panel_driver);
119{
120 return platform_driver_register(&htcherald_panel_driver);
121}
122
123static void __exit htcherald_panel_drv_cleanup(void)
124{
125 platform_driver_unregister(&htcherald_panel_driver);
126}
127
128module_init(htcherald_panel_drv_init);
129module_exit(htcherald_panel_drv_cleanup);
130
diff --git a/drivers/video/omap/lcd_inn1510.c b/drivers/video/omap/lcd_inn1510.c
index 3271f1643b26..b38b1dd15ce3 100644
--- a/drivers/video/omap/lcd_inn1510.c
+++ b/drivers/video/omap/lcd_inn1510.c
@@ -98,7 +98,7 @@ static int innovator1510_panel_resume(struct platform_device *pdev)
98 return 0; 98 return 0;
99} 99}
100 100
101struct platform_driver innovator1510_panel_driver = { 101static struct platform_driver innovator1510_panel_driver = {
102 .probe = innovator1510_panel_probe, 102 .probe = innovator1510_panel_probe,
103 .remove = innovator1510_panel_remove, 103 .remove = innovator1510_panel_remove,
104 .suspend = innovator1510_panel_suspend, 104 .suspend = innovator1510_panel_suspend,
@@ -109,16 +109,4 @@ struct platform_driver innovator1510_panel_driver = {
109 }, 109 },
110}; 110};
111 111
112static int __init innovator1510_panel_drv_init(void) 112module_platform_driver(innovator1510_panel_driver);
113{
114 return platform_driver_register(&innovator1510_panel_driver);
115}
116
117static void __exit innovator1510_panel_drv_cleanup(void)
118{
119 platform_driver_unregister(&innovator1510_panel_driver);
120}
121
122module_init(innovator1510_panel_drv_init);
123module_exit(innovator1510_panel_drv_cleanup);
124
diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/omap/lcd_inn1610.c
index 12cc52a70f96..7e8bd8e08a98 100644
--- a/drivers/video/omap/lcd_inn1610.c
+++ b/drivers/video/omap/lcd_inn1610.c
@@ -122,7 +122,7 @@ static int innovator1610_panel_resume(struct platform_device *pdev)
122 return 0; 122 return 0;
123} 123}
124 124
125struct platform_driver innovator1610_panel_driver = { 125static struct platform_driver innovator1610_panel_driver = {
126 .probe = innovator1610_panel_probe, 126 .probe = innovator1610_panel_probe,
127 .remove = innovator1610_panel_remove, 127 .remove = innovator1610_panel_remove,
128 .suspend = innovator1610_panel_suspend, 128 .suspend = innovator1610_panel_suspend,
@@ -133,16 +133,4 @@ struct platform_driver innovator1610_panel_driver = {
133 }, 133 },
134}; 134};
135 135
136static int __init innovator1610_panel_drv_init(void) 136module_platform_driver(innovator1610_panel_driver);
137{
138 return platform_driver_register(&innovator1610_panel_driver);
139}
140
141static void __exit innovator1610_panel_drv_cleanup(void)
142{
143 platform_driver_unregister(&innovator1610_panel_driver);
144}
145
146module_init(innovator1610_panel_drv_init);
147module_exit(innovator1610_panel_drv_cleanup);
148
diff --git a/drivers/video/omap/lcd_mipid.c b/drivers/video/omap/lcd_mipid.c
index eb381db7fe51..8d546dd55e81 100644
--- a/drivers/video/omap/lcd_mipid.c
+++ b/drivers/video/omap/lcd_mipid.c
@@ -603,7 +603,6 @@ static int mipid_spi_remove(struct spi_device *spi)
603static struct spi_driver mipid_spi_driver = { 603static struct spi_driver mipid_spi_driver = {
604 .driver = { 604 .driver = {
605 .name = MIPID_MODULE_NAME, 605 .name = MIPID_MODULE_NAME,
606 .bus = &spi_bus_type,
607 .owner = THIS_MODULE, 606 .owner = THIS_MODULE,
608 }, 607 },
609 .probe = mipid_spi_probe, 608 .probe = mipid_spi_probe,
diff --git a/drivers/video/omap/lcd_osk.c b/drivers/video/omap/lcd_osk.c
index 6f8d13c41202..5914220dfa9c 100644
--- a/drivers/video/omap/lcd_osk.c
+++ b/drivers/video/omap/lcd_osk.c
@@ -116,7 +116,7 @@ static int osk_panel_resume(struct platform_device *pdev)
116 return 0; 116 return 0;
117} 117}
118 118
119struct platform_driver osk_panel_driver = { 119static struct platform_driver osk_panel_driver = {
120 .probe = osk_panel_probe, 120 .probe = osk_panel_probe,
121 .remove = osk_panel_remove, 121 .remove = osk_panel_remove,
122 .suspend = osk_panel_suspend, 122 .suspend = osk_panel_suspend,
@@ -127,16 +127,4 @@ struct platform_driver osk_panel_driver = {
127 }, 127 },
128}; 128};
129 129
130static int __init osk_panel_drv_init(void) 130module_platform_driver(osk_panel_driver);
131{
132 return platform_driver_register(&osk_panel_driver);
133}
134
135static void __exit osk_panel_drv_cleanup(void)
136{
137 platform_driver_unregister(&osk_panel_driver);
138}
139
140module_init(osk_panel_drv_init);
141module_exit(osk_panel_drv_cleanup);
142
diff --git a/drivers/video/omap/lcd_palmte.c b/drivers/video/omap/lcd_palmte.c
index 4cb301750d02..88c31eb0cd6c 100644
--- a/drivers/video/omap/lcd_palmte.c
+++ b/drivers/video/omap/lcd_palmte.c
@@ -97,7 +97,7 @@ static int palmte_panel_resume(struct platform_device *pdev)
97 return 0; 97 return 0;
98} 98}
99 99
100struct platform_driver palmte_panel_driver = { 100static struct platform_driver palmte_panel_driver = {
101 .probe = palmte_panel_probe, 101 .probe = palmte_panel_probe,
102 .remove = palmte_panel_remove, 102 .remove = palmte_panel_remove,
103 .suspend = palmte_panel_suspend, 103 .suspend = palmte_panel_suspend,
@@ -108,16 +108,4 @@ struct platform_driver palmte_panel_driver = {
108 }, 108 },
109}; 109};
110 110
111static int __init palmte_panel_drv_init(void) 111module_platform_driver(palmte_panel_driver);
112{
113 return platform_driver_register(&palmte_panel_driver);
114}
115
116static void __exit palmte_panel_drv_cleanup(void)
117{
118 platform_driver_unregister(&palmte_panel_driver);
119}
120
121module_init(palmte_panel_drv_init);
122module_exit(palmte_panel_drv_cleanup);
123
diff --git a/drivers/video/omap/lcd_palmtt.c b/drivers/video/omap/lcd_palmtt.c
index b51b332e5a2b..aaf3c8ba1243 100644
--- a/drivers/video/omap/lcd_palmtt.c
+++ b/drivers/video/omap/lcd_palmtt.c
@@ -102,7 +102,7 @@ static int palmtt_panel_resume(struct platform_device *pdev)
102 return 0; 102 return 0;
103} 103}
104 104
105struct platform_driver palmtt_panel_driver = { 105static struct platform_driver palmtt_panel_driver = {
106 .probe = palmtt_panel_probe, 106 .probe = palmtt_panel_probe,
107 .remove = palmtt_panel_remove, 107 .remove = palmtt_panel_remove,
108 .suspend = palmtt_panel_suspend, 108 .suspend = palmtt_panel_suspend,
@@ -113,15 +113,4 @@ struct platform_driver palmtt_panel_driver = {
113 }, 113 },
114}; 114};
115 115
116static int __init palmtt_panel_drv_init(void) 116module_platform_driver(palmtt_panel_driver);
117{
118 return platform_driver_register(&palmtt_panel_driver);
119}
120
121static void __exit palmtt_panel_drv_cleanup(void)
122{
123 platform_driver_unregister(&palmtt_panel_driver);
124}
125
126module_init(palmtt_panel_drv_init);
127module_exit(palmtt_panel_drv_cleanup);
diff --git a/drivers/video/omap/lcd_palmz71.c b/drivers/video/omap/lcd_palmz71.c
index 2334e56536bc..3b7d8aa1cf34 100644
--- a/drivers/video/omap/lcd_palmz71.c
+++ b/drivers/video/omap/lcd_palmz71.c
@@ -98,7 +98,7 @@ static int palmz71_panel_resume(struct platform_device *pdev)
98 return 0; 98 return 0;
99} 99}
100 100
101struct platform_driver palmz71_panel_driver = { 101static struct platform_driver palmz71_panel_driver = {
102 .probe = palmz71_panel_probe, 102 .probe = palmz71_panel_probe,
103 .remove = palmz71_panel_remove, 103 .remove = palmz71_panel_remove,
104 .suspend = palmz71_panel_suspend, 104 .suspend = palmz71_panel_suspend,
@@ -109,15 +109,4 @@ struct platform_driver palmz71_panel_driver = {
109 }, 109 },
110}; 110};
111 111
112static int __init palmz71_panel_drv_init(void) 112module_platform_driver(palmz71_panel_driver);
113{
114 return platform_driver_register(&palmz71_panel_driver);
115}
116
117static void __exit palmz71_panel_drv_cleanup(void)
118{
119 platform_driver_unregister(&palmz71_panel_driver);
120}
121
122module_init(palmz71_panel_drv_init);
123module_exit(palmz71_panel_drv_cleanup);
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
index 8d8e1fe1901c..74d29b552901 100644
--- a/drivers/video/omap2/displays/Kconfig
+++ b/drivers/video/omap2/displays/Kconfig
@@ -41,7 +41,7 @@ config PANEL_NEC_NL8048HL11_01B
41 41
42config PANEL_PICODLP 42config PANEL_PICODLP
43 tristate "TI PICO DLP mini-projector" 43 tristate "TI PICO DLP mini-projector"
44 depends on OMAP2_DSS && I2C 44 depends on OMAP2_DSS_DPI && I2C
45 help 45 help
46 A mini-projector used in TI's SDP4430 and EVM boards 46 A mini-projector used in TI's SDP4430 and EVM boards
47 For more info please visit http://www.dlp.com/projector/ 47 For more info please visit http://www.dlp.com/projector/
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
index dbd59b8e5b36..51a87e149e24 100644
--- a/drivers/video/omap2/displays/panel-acx565akm.c
+++ b/drivers/video/omap2/displays/panel-acx565akm.c
@@ -803,7 +803,6 @@ static int acx565akm_spi_remove(struct spi_device *spi)
803static struct spi_driver acx565akm_spi_driver = { 803static struct spi_driver acx565akm_spi_driver = {
804 .driver = { 804 .driver = {
805 .name = "acx565akm", 805 .name = "acx565akm",
806 .bus = &spi_bus_type,
807 .owner = THIS_MODULE, 806 .owner = THIS_MODULE,
808 }, 807 },
809 .probe = acx565akm_spi_probe, 808 .probe = acx565akm_spi_probe,
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c
index 519c47d2057f..28b9a6d61b0f 100644
--- a/drivers/video/omap2/displays/panel-generic-dpi.c
+++ b/drivers/video/omap2/displays/panel-generic-dpi.c
@@ -297,6 +297,72 @@ static struct panel_config generic_dpi_panels[] = {
297 297
298 .name = "apollon", 298 .name = "apollon",
299 }, 299 },
300 /* FocalTech ETM070003DH6 */
301 {
302 {
303 .x_res = 800,
304 .y_res = 480,
305
306 .pixel_clock = 28000,
307
308 .hsw = 48,
309 .hfp = 40,
310 .hbp = 40,
311
312 .vsw = 3,
313 .vfp = 13,
314 .vbp = 29,
315 },
316 .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
317 OMAP_DSS_LCD_IHS,
318 .name = "focaltech_etm070003dh6",
319 },
320
321 /* Microtips Technologies - UMSH-8173MD */
322 {
323 {
324 .x_res = 800,
325 .y_res = 480,
326
327 .pixel_clock = 34560,
328
329 .hsw = 13,
330 .hfp = 101,
331 .hbp = 101,
332
333 .vsw = 23,
334 .vfp = 1,
335 .vbp = 1,
336 },
337 .acbi = 0x0,
338 .acb = 0x0,
339 .config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
340 OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC,
341 .power_on_delay = 0,
342 .power_off_delay = 0,
343 .name = "microtips_umsh_8173md",
344 },
345
346 /* OrtusTech COM43H4M10XTC */
347 {
348 {
349 .x_res = 480,
350 .y_res = 272,
351
352 .pixel_clock = 8000,
353
354 .hsw = 41,
355 .hfp = 8,
356 .hbp = 4,
357
358 .vsw = 10,
359 .vfp = 4,
360 .vbp = 2,
361 },
362 .config = OMAP_DSS_LCD_TFT,
363
364 .name = "ortustech_com43h4m10xtc",
365 },
300}; 366};
301 367
302struct panel_drv_data { 368struct panel_drv_data {
diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c
index 150e8bae35a1..dc9408dc93d1 100644
--- a/drivers/video/omap2/displays/panel-n8x0.c
+++ b/drivers/video/omap2/displays/panel-n8x0.c
@@ -708,7 +708,6 @@ static int mipid_spi_remove(struct spi_device *spi)
708static struct spi_driver mipid_spi_driver = { 708static struct spi_driver mipid_spi_driver = {
709 .driver = { 709 .driver = {
710 .name = "lcd_mipid", 710 .name = "lcd_mipid",
711 .bus = &spi_bus_type,
712 .owner = THIS_MODULE, 711 .owner = THIS_MODULE,
713 }, 712 },
714 .probe = mipid_spi_probe, 713 .probe = mipid_spi_probe,
diff --git a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
index 2ba9d0ca187c..0eb31caddca8 100644
--- a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
+++ b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
@@ -163,50 +163,93 @@ static void nec_8048_panel_remove(struct omap_dss_device *dssdev)
163 kfree(necd); 163 kfree(necd);
164} 164}
165 165
166static int nec_8048_panel_enable(struct omap_dss_device *dssdev) 166static int nec_8048_panel_power_on(struct omap_dss_device *dssdev)
167{ 167{
168 int r = 0; 168 int r;
169 struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev); 169 struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev);
170 struct backlight_device *bl = necd->bl; 170 struct backlight_device *bl = necd->bl;
171 171
172 if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
173 return 0;
174
175 r = omapdss_dpi_display_enable(dssdev);
176 if (r)
177 goto err0;
178
172 if (dssdev->platform_enable) { 179 if (dssdev->platform_enable) {
173 r = dssdev->platform_enable(dssdev); 180 r = dssdev->platform_enable(dssdev);
174 if (r) 181 if (r)
175 return r; 182 goto err1;
176 } 183 }
177 184
178 r = nec_8048_bl_update_status(bl); 185 r = nec_8048_bl_update_status(bl);
179 if (r < 0) 186 if (r < 0)
180 dev_err(&dssdev->dev, "failed to set lcd brightness\n"); 187 dev_err(&dssdev->dev, "failed to set lcd brightness\n");
181 188
182 r = omapdss_dpi_display_enable(dssdev); 189 return 0;
183 190err1:
191 omapdss_dpi_display_disable(dssdev);
192err0:
184 return r; 193 return r;
185} 194}
186 195
187static void nec_8048_panel_disable(struct omap_dss_device *dssdev) 196static void nec_8048_panel_power_off(struct omap_dss_device *dssdev)
188{ 197{
189 struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev); 198 struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev);
190 struct backlight_device *bl = necd->bl; 199 struct backlight_device *bl = necd->bl;
191 200
192 omapdss_dpi_display_disable(dssdev); 201 if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
202 return;
193 203
194 bl->props.brightness = 0; 204 bl->props.brightness = 0;
195 nec_8048_bl_update_status(bl); 205 nec_8048_bl_update_status(bl);
196 206
197 if (dssdev->platform_disable) 207 if (dssdev->platform_disable)
198 dssdev->platform_disable(dssdev); 208 dssdev->platform_disable(dssdev);
209
210 omapdss_dpi_display_disable(dssdev);
211}
212
213static int nec_8048_panel_enable(struct omap_dss_device *dssdev)
214{
215 int r;
216
217 r = nec_8048_panel_power_on(dssdev);
218 if (r)
219 return r;
220
221 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
222
223 return 0;
224}
225
226static void nec_8048_panel_disable(struct omap_dss_device *dssdev)
227{
228 nec_8048_panel_power_off(dssdev);
229
230 dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
199} 231}
200 232
201static int nec_8048_panel_suspend(struct omap_dss_device *dssdev) 233static int nec_8048_panel_suspend(struct omap_dss_device *dssdev)
202{ 234{
203 nec_8048_panel_disable(dssdev); 235 nec_8048_panel_power_off(dssdev);
236
237 dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
238
204 return 0; 239 return 0;
205} 240}
206 241
207static int nec_8048_panel_resume(struct omap_dss_device *dssdev) 242static int nec_8048_panel_resume(struct omap_dss_device *dssdev)
208{ 243{
209 return nec_8048_panel_enable(dssdev); 244 int r;
245
246 r = nec_8048_panel_power_on(dssdev);
247 if (r)
248 return r;
249
250 dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
251
252 return 0;
210} 253}
211 254
212static int nec_8048_recommended_bpp(struct omap_dss_device *dssdev) 255static int nec_8048_recommended_bpp(struct omap_dss_device *dssdev)
@@ -303,7 +346,6 @@ static struct spi_driver nec_8048_spi_driver = {
303 .resume = nec_8048_spi_resume, 346 .resume = nec_8048_spi_resume,
304 .driver = { 347 .driver = {
305 .name = "nec_8048_spi", 348 .name = "nec_8048_spi",
306 .bus = &spi_bus_type,
307 .owner = THIS_MODULE, 349 .owner = THIS_MODULE,
308 }, 350 },
309}; 351};
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index 80c3f6ab1a94..00c5c615585f 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -198,12 +198,6 @@ struct taal_data {
198 bool te_enabled; 198 bool te_enabled;
199 199
200 atomic_t do_update; 200 atomic_t do_update;
201 struct {
202 u16 x;
203 u16 y;
204 u16 w;
205 u16 h;
206 } update_region;
207 int channel; 201 int channel;
208 202
209 struct delayed_work te_timeout_work; 203 struct delayed_work te_timeout_work;
@@ -1188,6 +1182,10 @@ static int taal_power_on(struct omap_dss_device *dssdev)
1188 if (r) 1182 if (r)
1189 goto err; 1183 goto err;
1190 1184
1185 r = dsi_enable_video_output(dssdev, td->channel);
1186 if (r)
1187 goto err;
1188
1191 td->enabled = 1; 1189 td->enabled = 1;
1192 1190
1193 if (!td->intro_printed) { 1191 if (!td->intro_printed) {
@@ -1217,6 +1215,8 @@ static void taal_power_off(struct omap_dss_device *dssdev)
1217 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1215 struct taal_data *td = dev_get_drvdata(&dssdev->dev);
1218 int r; 1216 int r;
1219 1217
1218 dsi_disable_video_output(dssdev, td->channel);
1219
1220 r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_OFF); 1220 r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_OFF);
1221 if (!r) 1221 if (!r)
1222 r = taal_sleep_in(td); 1222 r = taal_sleep_in(td);
@@ -1394,12 +1394,8 @@ static irqreturn_t taal_te_isr(int irq, void *data)
1394 if (old) { 1394 if (old) {
1395 cancel_delayed_work(&td->te_timeout_work); 1395 cancel_delayed_work(&td->te_timeout_work);
1396 1396
1397 r = omap_dsi_update(dssdev, td->channel, 1397 r = omap_dsi_update(dssdev, td->channel, taal_framedone_cb,
1398 td->update_region.x, 1398 dssdev);
1399 td->update_region.y,
1400 td->update_region.w,
1401 td->update_region.h,
1402 taal_framedone_cb, dssdev);
1403 if (r) 1399 if (r)
1404 goto err; 1400 goto err;
1405 } 1401 }
@@ -1444,26 +1440,20 @@ static int taal_update(struct omap_dss_device *dssdev,
1444 goto err; 1440 goto err;
1445 } 1441 }
1446 1442
1447 r = omap_dsi_prepare_update(dssdev, &x, &y, &w, &h, true); 1443 /* XXX no need to send this every frame, but dsi break if not done */
1448 if (r) 1444 r = taal_set_update_window(td, 0, 0,
1449 goto err; 1445 td->panel_config->timings.x_res,
1450 1446 td->panel_config->timings.y_res);
1451 r = taal_set_update_window(td, x, y, w, h);
1452 if (r) 1447 if (r)
1453 goto err; 1448 goto err;
1454 1449
1455 if (td->te_enabled && panel_data->use_ext_te) { 1450 if (td->te_enabled && panel_data->use_ext_te) {
1456 td->update_region.x = x;
1457 td->update_region.y = y;
1458 td->update_region.w = w;
1459 td->update_region.h = h;
1460 barrier();
1461 schedule_delayed_work(&td->te_timeout_work, 1451 schedule_delayed_work(&td->te_timeout_work,
1462 msecs_to_jiffies(250)); 1452 msecs_to_jiffies(250));
1463 atomic_set(&td->do_update, 1); 1453 atomic_set(&td->do_update, 1);
1464 } else { 1454 } else {
1465 r = omap_dsi_update(dssdev, td->channel, x, y, w, h, 1455 r = omap_dsi_update(dssdev, td->channel, taal_framedone_cb,
1466 taal_framedone_cb, dssdev); 1456 dssdev);
1467 if (r) 1457 if (r)
1468 goto err; 1458 goto err;
1469 } 1459 }
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
index 2462b9ec6662..e6649aa89591 100644
--- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
+++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c
@@ -512,7 +512,6 @@ static int __devexit tpo_td043_spi_remove(struct spi_device *spi)
512static struct spi_driver tpo_td043_spi_driver = { 512static struct spi_driver tpo_td043_spi_driver = {
513 .driver = { 513 .driver = {
514 .name = "tpo_td043mtea1_panel_spi", 514 .name = "tpo_td043mtea1_panel_spi",
515 .bus = &spi_bus_type,
516 .owner = THIS_MODULE, 515 .owner = THIS_MODULE,
517 }, 516 },
518 .probe = tpo_td043_spi_probe, 517 .probe = tpo_td043_spi_probe,
diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/omap2/dss/Makefile
index bd34ac5b2026..5c450b0f94d0 100644
--- a/drivers/video/omap2/dss/Makefile
+++ b/drivers/video/omap2/dss/Makefile
@@ -1,5 +1,6 @@
1obj-$(CONFIG_OMAP2_DSS) += omapdss.o 1obj-$(CONFIG_OMAP2_DSS) += omapdss.o
2omapdss-y := core.o dss.o dss_features.o dispc.o display.o manager.o overlay.o 2omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \
3 manager.o overlay.o apply.o
3omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o 4omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
4omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o 5omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
5omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o 6omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
new file mode 100644
index 000000000000..052dc874cd3d
--- /dev/null
+++ b/drivers/video/omap2/dss/apply.c
@@ -0,0 +1,1324 @@
1/*
2 * Copyright (C) 2011 Texas Instruments
3 * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#define DSS_SUBSYS_NAME "APPLY"
19
20#include <linux/kernel.h>
21#include <linux/slab.h>
22#include <linux/spinlock.h>
23#include <linux/jiffies.h>
24
25#include <video/omapdss.h>
26
27#include "dss.h"
28#include "dss_features.h"
29
30/*
31 * We have 4 levels of cache for the dispc settings. First two are in SW and
32 * the latter two in HW.
33 *
34 * set_info()
35 * v
36 * +--------------------+
37 * | user_info |
38 * +--------------------+
39 * v
40 * apply()
41 * v
42 * +--------------------+
43 * | info |
44 * +--------------------+
45 * v
46 * write_regs()
47 * v
48 * +--------------------+
49 * | shadow registers |
50 * +--------------------+
51 * v
52 * VFP or lcd/digit_enable
53 * v
54 * +--------------------+
55 * | registers |
56 * +--------------------+
57 */
58
59struct ovl_priv_data {
60
61 bool user_info_dirty;
62 struct omap_overlay_info user_info;
63
64 bool info_dirty;
65 struct omap_overlay_info info;
66
67 bool shadow_info_dirty;
68
69 bool extra_info_dirty;
70 bool shadow_extra_info_dirty;
71
72 bool enabled;
73 enum omap_channel channel;
74 u32 fifo_low, fifo_high;
75
76 /*
77 * True if overlay is to be enabled. Used to check and calculate configs
78 * for the overlay before it is enabled in the HW.
79 */
80 bool enabling;
81};
82
83struct mgr_priv_data {
84
85 bool user_info_dirty;
86 struct omap_overlay_manager_info user_info;
87
88 bool info_dirty;
89 struct omap_overlay_manager_info info;
90
91 bool shadow_info_dirty;
92
93 /* If true, GO bit is up and shadow registers cannot be written.
94 * Never true for manual update displays */
95 bool busy;
96
97 /* If true, dispc output is enabled */
98 bool updating;
99
100 /* If true, a display is enabled using this manager */
101 bool enabled;
102};
103
104static struct {
105 struct ovl_priv_data ovl_priv_data_array[MAX_DSS_OVERLAYS];
106 struct mgr_priv_data mgr_priv_data_array[MAX_DSS_MANAGERS];
107
108 bool irq_enabled;
109} dss_data;
110
111/* protects dss_data */
112static spinlock_t data_lock;
113/* lock for blocking functions */
114static DEFINE_MUTEX(apply_lock);
115static DECLARE_COMPLETION(extra_updated_completion);
116
117static void dss_register_vsync_isr(void);
118
119static struct ovl_priv_data *get_ovl_priv(struct omap_overlay *ovl)
120{
121 return &dss_data.ovl_priv_data_array[ovl->id];
122}
123
124static struct mgr_priv_data *get_mgr_priv(struct omap_overlay_manager *mgr)
125{
126 return &dss_data.mgr_priv_data_array[mgr->id];
127}
128
129void dss_apply_init(void)
130{
131 const int num_ovls = dss_feat_get_num_ovls();
132 int i;
133
134 spin_lock_init(&data_lock);
135
136 for (i = 0; i < num_ovls; ++i) {
137 struct ovl_priv_data *op;
138
139 op = &dss_data.ovl_priv_data_array[i];
140
141 op->info.global_alpha = 255;
142
143 switch (i) {
144 case 0:
145 op->info.zorder = 0;
146 break;
147 case 1:
148 op->info.zorder =
149 dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0;
150 break;
151 case 2:
152 op->info.zorder =
153 dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0;
154 break;
155 case 3:
156 op->info.zorder =
157 dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0;
158 break;
159 }
160
161 op->user_info = op->info;
162 }
163}
164
165static bool ovl_manual_update(struct omap_overlay *ovl)
166{
167 return ovl->manager->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
168}
169
170static bool mgr_manual_update(struct omap_overlay_manager *mgr)
171{
172 return mgr->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
173}
174
175static int dss_check_settings_low(struct omap_overlay_manager *mgr,
176 struct omap_dss_device *dssdev, bool applying)
177{
178 struct omap_overlay_info *oi;
179 struct omap_overlay_manager_info *mi;
180 struct omap_overlay *ovl;
181 struct omap_overlay_info *ois[MAX_DSS_OVERLAYS];
182 struct ovl_priv_data *op;
183 struct mgr_priv_data *mp;
184
185 mp = get_mgr_priv(mgr);
186
187 if (applying && mp->user_info_dirty)
188 mi = &mp->user_info;
189 else
190 mi = &mp->info;
191
192 /* collect the infos to be tested into the array */
193 list_for_each_entry(ovl, &mgr->overlays, list) {
194 op = get_ovl_priv(ovl);
195
196 if (!op->enabled && !op->enabling)
197 oi = NULL;
198 else if (applying && op->user_info_dirty)
199 oi = &op->user_info;
200 else
201 oi = &op->info;
202
203 ois[ovl->id] = oi;
204 }
205
206 return dss_mgr_check(mgr, dssdev, mi, ois);
207}
208
209/*
210 * check manager and overlay settings using overlay_info from data->info
211 */
212static int dss_check_settings(struct omap_overlay_manager *mgr,
213 struct omap_dss_device *dssdev)
214{
215 return dss_check_settings_low(mgr, dssdev, false);
216}
217
218/*
219 * check manager and overlay settings using overlay_info from ovl->info if
220 * dirty and from data->info otherwise
221 */
222static int dss_check_settings_apply(struct omap_overlay_manager *mgr,
223 struct omap_dss_device *dssdev)
224{
225 return dss_check_settings_low(mgr, dssdev, true);
226}
227
228static bool need_isr(void)
229{
230 const int num_mgrs = dss_feat_get_num_mgrs();
231 int i;
232
233 for (i = 0; i < num_mgrs; ++i) {
234 struct omap_overlay_manager *mgr;
235 struct mgr_priv_data *mp;
236 struct omap_overlay *ovl;
237
238 mgr = omap_dss_get_overlay_manager(i);
239 mp = get_mgr_priv(mgr);
240
241 if (!mp->enabled)
242 continue;
243
244 if (mgr_manual_update(mgr)) {
245 /* to catch FRAMEDONE */
246 if (mp->updating)
247 return true;
248 } else {
249 /* to catch GO bit going down */
250 if (mp->busy)
251 return true;
252
253 /* to write new values to registers */
254 if (mp->info_dirty)
255 return true;
256
257 /* to set GO bit */
258 if (mp->shadow_info_dirty)
259 return true;
260
261 list_for_each_entry(ovl, &mgr->overlays, list) {
262 struct ovl_priv_data *op;
263
264 op = get_ovl_priv(ovl);
265
266 /*
267 * NOTE: we check extra_info flags even for
268 * disabled overlays, as extra_infos need to be
269 * always written.
270 */
271
272 /* to write new values to registers */
273 if (op->extra_info_dirty)
274 return true;
275
276 /* to set GO bit */
277 if (op->shadow_extra_info_dirty)
278 return true;
279
280 if (!op->enabled)
281 continue;
282
283 /* to write new values to registers */
284 if (op->info_dirty)
285 return true;
286
287 /* to set GO bit */
288 if (op->shadow_info_dirty)
289 return true;
290 }
291 }
292 }
293
294 return false;
295}
296
297static bool need_go(struct omap_overlay_manager *mgr)
298{
299 struct omap_overlay *ovl;
300 struct mgr_priv_data *mp;
301 struct ovl_priv_data *op;
302
303 mp = get_mgr_priv(mgr);
304
305 if (mp->shadow_info_dirty)
306 return true;
307
308 list_for_each_entry(ovl, &mgr->overlays, list) {
309 op = get_ovl_priv(ovl);
310 if (op->shadow_info_dirty || op->shadow_extra_info_dirty)
311 return true;
312 }
313
314 return false;
315}
316
317/* returns true if an extra_info field is currently being updated */
318static bool extra_info_update_ongoing(void)
319{
320 const int num_ovls = omap_dss_get_num_overlays();
321 struct ovl_priv_data *op;
322 struct omap_overlay *ovl;
323 struct mgr_priv_data *mp;
324 int i;
325
326 for (i = 0; i < num_ovls; ++i) {
327 ovl = omap_dss_get_overlay(i);
328 op = get_ovl_priv(ovl);
329
330 if (!ovl->manager)
331 continue;
332
333 mp = get_mgr_priv(ovl->manager);
334
335 if (!mp->enabled)
336 continue;
337
338 if (!mp->updating)
339 continue;
340
341 if (op->extra_info_dirty || op->shadow_extra_info_dirty)
342 return true;
343 }
344
345 return false;
346}
347
348/* wait until no extra_info updates are pending */
349static void wait_pending_extra_info_updates(void)
350{
351 bool updating;
352 unsigned long flags;
353 unsigned long t;
354
355 spin_lock_irqsave(&data_lock, flags);
356
357 updating = extra_info_update_ongoing();
358
359 if (!updating) {
360 spin_unlock_irqrestore(&data_lock, flags);
361 return;
362 }
363
364 init_completion(&extra_updated_completion);
365
366 spin_unlock_irqrestore(&data_lock, flags);
367
368 t = msecs_to_jiffies(500);
369 wait_for_completion_timeout(&extra_updated_completion, t);
370
371 updating = extra_info_update_ongoing();
372
373 WARN_ON(updating);
374}
375
376int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
377{
378 unsigned long timeout = msecs_to_jiffies(500);
379 struct mgr_priv_data *mp;
380 u32 irq;
381 int r;
382 int i;
383 struct omap_dss_device *dssdev = mgr->device;
384
385 if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
386 return 0;
387
388 if (mgr_manual_update(mgr))
389 return 0;
390
391 irq = dispc_mgr_get_vsync_irq(mgr->id);
392
393 mp = get_mgr_priv(mgr);
394 i = 0;
395 while (1) {
396 unsigned long flags;
397 bool shadow_dirty, dirty;
398
399 spin_lock_irqsave(&data_lock, flags);
400 dirty = mp->info_dirty;
401 shadow_dirty = mp->shadow_info_dirty;
402 spin_unlock_irqrestore(&data_lock, flags);
403
404 if (!dirty && !shadow_dirty) {
405 r = 0;
406 break;
407 }
408
409 /* 4 iterations is the worst case:
410 * 1 - initial iteration, dirty = true (between VFP and VSYNC)
411 * 2 - first VSYNC, dirty = true
412 * 3 - dirty = false, shadow_dirty = true
413 * 4 - shadow_dirty = false */
414 if (i++ == 3) {
415 DSSERR("mgr(%d)->wait_for_go() not finishing\n",
416 mgr->id);
417 r = 0;
418 break;
419 }
420
421 r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
422 if (r == -ERESTARTSYS)
423 break;
424
425 if (r) {
426 DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id);
427 break;
428 }
429 }
430
431 return r;
432}
433
434int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
435{
436 unsigned long timeout = msecs_to_jiffies(500);
437 struct ovl_priv_data *op;
438 struct omap_dss_device *dssdev;
439 u32 irq;
440 int r;
441 int i;
442
443 if (!ovl->manager)
444 return 0;
445
446 dssdev = ovl->manager->device;
447
448 if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
449 return 0;
450
451 if (ovl_manual_update(ovl))
452 return 0;
453
454 irq = dispc_mgr_get_vsync_irq(ovl->manager->id);
455
456 op = get_ovl_priv(ovl);
457 i = 0;
458 while (1) {
459 unsigned long flags;
460 bool shadow_dirty, dirty;
461
462 spin_lock_irqsave(&data_lock, flags);
463 dirty = op->info_dirty;
464 shadow_dirty = op->shadow_info_dirty;
465 spin_unlock_irqrestore(&data_lock, flags);
466
467 if (!dirty && !shadow_dirty) {
468 r = 0;
469 break;
470 }
471
472 /* 4 iterations is the worst case:
473 * 1 - initial iteration, dirty = true (between VFP and VSYNC)
474 * 2 - first VSYNC, dirty = true
475 * 3 - dirty = false, shadow_dirty = true
476 * 4 - shadow_dirty = false */
477 if (i++ == 3) {
478 DSSERR("ovl(%d)->wait_for_go() not finishing\n",
479 ovl->id);
480 r = 0;
481 break;
482 }
483
484 r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
485 if (r == -ERESTARTSYS)
486 break;
487
488 if (r) {
489 DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id);
490 break;
491 }
492 }
493
494 return r;
495}
496
497static void dss_ovl_write_regs(struct omap_overlay *ovl)
498{
499 struct ovl_priv_data *op = get_ovl_priv(ovl);
500 struct omap_overlay_info *oi;
501 bool ilace, replication;
502 struct mgr_priv_data *mp;
503 int r;
504
505 DSSDBGF("%d", ovl->id);
506
507 if (!op->enabled || !op->info_dirty)
508 return;
509
510 oi = &op->info;
511
512 replication = dss_use_replication(ovl->manager->device, oi->color_mode);
513
514 ilace = ovl->manager->device->type == OMAP_DISPLAY_TYPE_VENC;
515
516 r = dispc_ovl_setup(ovl->id, oi, ilace, replication);
517 if (r) {
518 /*
519 * We can't do much here, as this function can be called from
520 * vsync interrupt.
521 */
522 DSSERR("dispc_ovl_setup failed for ovl %d\n", ovl->id);
523
524 /* This will leave fifo configurations in a nonoptimal state */
525 op->enabled = false;
526 dispc_ovl_enable(ovl->id, false);
527 return;
528 }
529
530 mp = get_mgr_priv(ovl->manager);
531
532 op->info_dirty = false;
533 if (mp->updating)
534 op->shadow_info_dirty = true;
535}
536
537static void dss_ovl_write_regs_extra(struct omap_overlay *ovl)
538{
539 struct ovl_priv_data *op = get_ovl_priv(ovl);
540 struct mgr_priv_data *mp;
541
542 DSSDBGF("%d", ovl->id);
543
544 if (!op->extra_info_dirty)
545 return;
546
547 /* note: write also when op->enabled == false, so that the ovl gets
548 * disabled */
549
550 dispc_ovl_enable(ovl->id, op->enabled);
551 dispc_ovl_set_channel_out(ovl->id, op->channel);
552 dispc_ovl_set_fifo_threshold(ovl->id, op->fifo_low, op->fifo_high);
553
554 mp = get_mgr_priv(ovl->manager);
555
556 op->extra_info_dirty = false;
557 if (mp->updating)
558 op->shadow_extra_info_dirty = true;
559}
560
561static void dss_mgr_write_regs(struct omap_overlay_manager *mgr)
562{
563 struct mgr_priv_data *mp = get_mgr_priv(mgr);
564 struct omap_overlay *ovl;
565
566 DSSDBGF("%d", mgr->id);
567
568 if (!mp->enabled)
569 return;
570
571 WARN_ON(mp->busy);
572
573 /* Commit overlay settings */
574 list_for_each_entry(ovl, &mgr->overlays, list) {
575 dss_ovl_write_regs(ovl);
576 dss_ovl_write_regs_extra(ovl);
577 }
578
579 if (mp->info_dirty) {
580 dispc_mgr_setup(mgr->id, &mp->info);
581
582 mp->info_dirty = false;
583 if (mp->updating)
584 mp->shadow_info_dirty = true;
585 }
586}
587
588static void dss_write_regs(void)
589{
590 const int num_mgrs = omap_dss_get_num_overlay_managers();
591 int i;
592
593 for (i = 0; i < num_mgrs; ++i) {
594 struct omap_overlay_manager *mgr;
595 struct mgr_priv_data *mp;
596 int r;
597
598 mgr = omap_dss_get_overlay_manager(i);
599 mp = get_mgr_priv(mgr);
600
601 if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
602 continue;
603
604 r = dss_check_settings(mgr, mgr->device);
605 if (r) {
606 DSSERR("cannot write registers for manager %s: "
607 "illegal configuration\n", mgr->name);
608 continue;
609 }
610
611 dss_mgr_write_regs(mgr);
612 }
613}
614
615static void dss_set_go_bits(void)
616{
617 const int num_mgrs = omap_dss_get_num_overlay_managers();
618 int i;
619
620 for (i = 0; i < num_mgrs; ++i) {
621 struct omap_overlay_manager *mgr;
622 struct mgr_priv_data *mp;
623
624 mgr = omap_dss_get_overlay_manager(i);
625 mp = get_mgr_priv(mgr);
626
627 if (!mp->enabled || mgr_manual_update(mgr) || mp->busy)
628 continue;
629
630 if (!need_go(mgr))
631 continue;
632
633 mp->busy = true;
634
635 if (!dss_data.irq_enabled && need_isr())
636 dss_register_vsync_isr();
637
638 dispc_mgr_go(mgr->id);
639 }
640
641}
642
643void dss_mgr_start_update(struct omap_overlay_manager *mgr)
644{
645 struct mgr_priv_data *mp = get_mgr_priv(mgr);
646 unsigned long flags;
647 int r;
648
649 spin_lock_irqsave(&data_lock, flags);
650
651 WARN_ON(mp->updating);
652
653 r = dss_check_settings(mgr, mgr->device);
654 if (r) {
655 DSSERR("cannot start manual update: illegal configuration\n");
656 spin_unlock_irqrestore(&data_lock, flags);
657 return;
658 }
659
660 dss_mgr_write_regs(mgr);
661
662 mp->updating = true;
663
664 if (!dss_data.irq_enabled && need_isr())
665 dss_register_vsync_isr();
666
667 dispc_mgr_enable(mgr->id, true);
668
669 spin_unlock_irqrestore(&data_lock, flags);
670}
671
672static void dss_apply_irq_handler(void *data, u32 mask);
673
674static void dss_register_vsync_isr(void)
675{
676 const int num_mgrs = dss_feat_get_num_mgrs();
677 u32 mask;
678 int r, i;
679
680 mask = 0;
681 for (i = 0; i < num_mgrs; ++i)
682 mask |= dispc_mgr_get_vsync_irq(i);
683
684 for (i = 0; i < num_mgrs; ++i)
685 mask |= dispc_mgr_get_framedone_irq(i);
686
687 r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, mask);
688 WARN_ON(r);
689
690 dss_data.irq_enabled = true;
691}
692
693static void dss_unregister_vsync_isr(void)
694{
695 const int num_mgrs = dss_feat_get_num_mgrs();
696 u32 mask;
697 int r, i;
698
699 mask = 0;
700 for (i = 0; i < num_mgrs; ++i)
701 mask |= dispc_mgr_get_vsync_irq(i);
702
703 for (i = 0; i < num_mgrs; ++i)
704 mask |= dispc_mgr_get_framedone_irq(i);
705
706 r = omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, mask);
707 WARN_ON(r);
708
709 dss_data.irq_enabled = false;
710}
711
712static void mgr_clear_shadow_dirty(struct omap_overlay_manager *mgr)
713{
714 struct omap_overlay *ovl;
715 struct mgr_priv_data *mp;
716 struct ovl_priv_data *op;
717
718 mp = get_mgr_priv(mgr);
719 mp->shadow_info_dirty = false;
720
721 list_for_each_entry(ovl, &mgr->overlays, list) {
722 op = get_ovl_priv(ovl);
723 op->shadow_info_dirty = false;
724 op->shadow_extra_info_dirty = false;
725 }
726}
727
728static void dss_apply_irq_handler(void *data, u32 mask)
729{
730 const int num_mgrs = dss_feat_get_num_mgrs();
731 int i;
732 bool extra_updating;
733
734 spin_lock(&data_lock);
735
736 /* clear busy, updating flags, shadow_dirty flags */
737 for (i = 0; i < num_mgrs; i++) {
738 struct omap_overlay_manager *mgr;
739 struct mgr_priv_data *mp;
740 bool was_updating;
741
742 mgr = omap_dss_get_overlay_manager(i);
743 mp = get_mgr_priv(mgr);
744
745 if (!mp->enabled)
746 continue;
747
748 was_updating = mp->updating;
749 mp->updating = dispc_mgr_is_enabled(i);
750
751 if (!mgr_manual_update(mgr)) {
752 bool was_busy = mp->busy;
753 mp->busy = dispc_mgr_go_busy(i);
754
755 if (was_busy && !mp->busy)
756 mgr_clear_shadow_dirty(mgr);
757 } else {
758 if (was_updating && !mp->updating)
759 mgr_clear_shadow_dirty(mgr);
760 }
761 }
762
763 dss_write_regs();
764 dss_set_go_bits();
765
766 extra_updating = extra_info_update_ongoing();
767 if (!extra_updating)
768 complete_all(&extra_updated_completion);
769
770 if (!need_isr())
771 dss_unregister_vsync_isr();
772
773 spin_unlock(&data_lock);
774}
775
776static void omap_dss_mgr_apply_ovl(struct omap_overlay *ovl)
777{
778 struct ovl_priv_data *op;
779
780 op = get_ovl_priv(ovl);
781
782 if (!op->user_info_dirty)
783 return;
784
785 op->user_info_dirty = false;
786 op->info_dirty = true;
787 op->info = op->user_info;
788}
789
790static void omap_dss_mgr_apply_mgr(struct omap_overlay_manager *mgr)
791{
792 struct mgr_priv_data *mp;
793
794 mp = get_mgr_priv(mgr);
795
796 if (!mp->user_info_dirty)
797 return;
798
799 mp->user_info_dirty = false;
800 mp->info_dirty = true;
801 mp->info = mp->user_info;
802}
803
804int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
805{
806 unsigned long flags;
807 struct omap_overlay *ovl;
808 int r;
809
810 DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
811
812 spin_lock_irqsave(&data_lock, flags);
813
814 r = dss_check_settings_apply(mgr, mgr->device);
815 if (r) {
816 spin_unlock_irqrestore(&data_lock, flags);
817 DSSERR("failed to apply settings: illegal configuration.\n");
818 return r;
819 }
820
821 /* Configure overlays */
822 list_for_each_entry(ovl, &mgr->overlays, list)
823 omap_dss_mgr_apply_ovl(ovl);
824
825 /* Configure manager */
826 omap_dss_mgr_apply_mgr(mgr);
827
828 dss_write_regs();
829 dss_set_go_bits();
830
831 spin_unlock_irqrestore(&data_lock, flags);
832
833 return 0;
834}
835
836static void dss_apply_ovl_enable(struct omap_overlay *ovl, bool enable)
837{
838 struct ovl_priv_data *op;
839
840 op = get_ovl_priv(ovl);
841
842 if (op->enabled == enable)
843 return;
844
845 op->enabled = enable;
846 op->extra_info_dirty = true;
847}
848
849static void dss_apply_ovl_fifo_thresholds(struct omap_overlay *ovl,
850 u32 fifo_low, u32 fifo_high)
851{
852 struct ovl_priv_data *op = get_ovl_priv(ovl);
853
854 if (op->fifo_low == fifo_low && op->fifo_high == fifo_high)
855 return;
856
857 op->fifo_low = fifo_low;
858 op->fifo_high = fifo_high;
859 op->extra_info_dirty = true;
860}
861
862static void dss_ovl_setup_fifo(struct omap_overlay *ovl)
863{
864 struct ovl_priv_data *op = get_ovl_priv(ovl);
865 struct omap_dss_device *dssdev;
866 u32 size, burst_size;
867 u32 fifo_low, fifo_high;
868
869 if (!op->enabled && !op->enabling)
870 return;
871
872 dssdev = ovl->manager->device;
873
874 size = dispc_ovl_get_fifo_size(ovl->id);
875
876 burst_size = dispc_ovl_get_burst_size(ovl->id);
877
878 switch (dssdev->type) {
879 case OMAP_DISPLAY_TYPE_DPI:
880 case OMAP_DISPLAY_TYPE_DBI:
881 case OMAP_DISPLAY_TYPE_SDI:
882 case OMAP_DISPLAY_TYPE_VENC:
883 case OMAP_DISPLAY_TYPE_HDMI:
884 default_get_overlay_fifo_thresholds(ovl->id, size,
885 burst_size, &fifo_low, &fifo_high);
886 break;
887#ifdef CONFIG_OMAP2_DSS_DSI
888 case OMAP_DISPLAY_TYPE_DSI:
889 dsi_get_overlay_fifo_thresholds(ovl->id, size,
890 burst_size, &fifo_low, &fifo_high);
891 break;
892#endif
893 default:
894 BUG();
895 }
896
897 dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high);
898}
899
900static void dss_mgr_setup_fifos(struct omap_overlay_manager *mgr)
901{
902 struct omap_overlay *ovl;
903 struct mgr_priv_data *mp;
904
905 mp = get_mgr_priv(mgr);
906
907 if (!mp->enabled)
908 return;
909
910 list_for_each_entry(ovl, &mgr->overlays, list)
911 dss_ovl_setup_fifo(ovl);
912}
913
914static void dss_setup_fifos(void)
915{
916 const int num_mgrs = omap_dss_get_num_overlay_managers();
917 struct omap_overlay_manager *mgr;
918 int i;
919
920 for (i = 0; i < num_mgrs; ++i) {
921 mgr = omap_dss_get_overlay_manager(i);
922 dss_mgr_setup_fifos(mgr);
923 }
924}
925
926int dss_mgr_enable(struct omap_overlay_manager *mgr)
927{
928 struct mgr_priv_data *mp = get_mgr_priv(mgr);
929 unsigned long flags;
930 int r;
931
932 mutex_lock(&apply_lock);
933
934 if (mp->enabled)
935 goto out;
936
937 spin_lock_irqsave(&data_lock, flags);
938
939 mp->enabled = true;
940
941 r = dss_check_settings(mgr, mgr->device);
942 if (r) {
943 DSSERR("failed to enable manager %d: check_settings failed\n",
944 mgr->id);
945 goto err;
946 }
947
948 dss_setup_fifos();
949
950 dss_write_regs();
951 dss_set_go_bits();
952
953 if (!mgr_manual_update(mgr))
954 mp->updating = true;
955
956 spin_unlock_irqrestore(&data_lock, flags);
957
958 if (!mgr_manual_update(mgr))
959 dispc_mgr_enable(mgr->id, true);
960
961out:
962 mutex_unlock(&apply_lock);
963
964 return 0;
965
966err:
967 mp->enabled = false;
968 spin_unlock_irqrestore(&data_lock, flags);
969 mutex_unlock(&apply_lock);
970 return r;
971}
972
973void dss_mgr_disable(struct omap_overlay_manager *mgr)
974{
975 struct mgr_priv_data *mp = get_mgr_priv(mgr);
976 unsigned long flags;
977
978 mutex_lock(&apply_lock);
979
980 if (!mp->enabled)
981 goto out;
982
983 if (!mgr_manual_update(mgr))
984 dispc_mgr_enable(mgr->id, false);
985
986 spin_lock_irqsave(&data_lock, flags);
987
988 mp->updating = false;
989 mp->enabled = false;
990
991 spin_unlock_irqrestore(&data_lock, flags);
992
993out:
994 mutex_unlock(&apply_lock);
995}
996
997int dss_mgr_set_info(struct omap_overlay_manager *mgr,
998 struct omap_overlay_manager_info *info)
999{
1000 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1001 unsigned long flags;
1002 int r;
1003
1004 r = dss_mgr_simple_check(mgr, info);
1005 if (r)
1006 return r;
1007
1008 spin_lock_irqsave(&data_lock, flags);
1009
1010 mp->user_info = *info;
1011 mp->user_info_dirty = true;
1012
1013 spin_unlock_irqrestore(&data_lock, flags);
1014
1015 return 0;
1016}
1017
1018void dss_mgr_get_info(struct omap_overlay_manager *mgr,
1019 struct omap_overlay_manager_info *info)
1020{
1021 struct mgr_priv_data *mp = get_mgr_priv(mgr);
1022 unsigned long flags;
1023
1024 spin_lock_irqsave(&data_lock, flags);
1025
1026 *info = mp->user_info;
1027
1028 spin_unlock_irqrestore(&data_lock, flags);
1029}
1030
1031int dss_mgr_set_device(struct omap_overlay_manager *mgr,
1032 struct omap_dss_device *dssdev)
1033{
1034 int r;
1035
1036 mutex_lock(&apply_lock);
1037
1038 if (dssdev->manager) {
1039 DSSERR("display '%s' already has a manager '%s'\n",
1040 dssdev->name, dssdev->manager->name);
1041 r = -EINVAL;
1042 goto err;
1043 }
1044
1045 if ((mgr->supported_displays & dssdev->type) == 0) {
1046 DSSERR("display '%s' does not support manager '%s'\n",
1047 dssdev->name, mgr->name);
1048 r = -EINVAL;
1049 goto err;
1050 }
1051
1052 dssdev->manager = mgr;
1053 mgr->device = dssdev;
1054
1055 mutex_unlock(&apply_lock);
1056
1057 return 0;
1058err:
1059 mutex_unlock(&apply_lock);
1060 return r;
1061}
1062
1063int dss_mgr_unset_device(struct omap_overlay_manager *mgr)
1064{
1065 int r;
1066
1067 mutex_lock(&apply_lock);
1068
1069 if (!mgr->device) {
1070 DSSERR("failed to unset display, display not set.\n");
1071 r = -EINVAL;
1072 goto err;
1073 }
1074
1075 /*
1076 * Don't allow currently enabled displays to have the overlay manager
1077 * pulled out from underneath them
1078 */
1079 if (mgr->device->state != OMAP_DSS_DISPLAY_DISABLED) {
1080 r = -EINVAL;
1081 goto err;
1082 }
1083
1084 mgr->device->manager = NULL;
1085 mgr->device = NULL;
1086
1087 mutex_unlock(&apply_lock);
1088
1089 return 0;
1090err:
1091 mutex_unlock(&apply_lock);
1092 return r;
1093}
1094
1095
1096int dss_ovl_set_info(struct omap_overlay *ovl,
1097 struct omap_overlay_info *info)
1098{
1099 struct ovl_priv_data *op = get_ovl_priv(ovl);
1100 unsigned long flags;
1101 int r;
1102
1103 r = dss_ovl_simple_check(ovl, info);
1104 if (r)
1105 return r;
1106
1107 spin_lock_irqsave(&data_lock, flags);
1108
1109 op->user_info = *info;
1110 op->user_info_dirty = true;
1111
1112 spin_unlock_irqrestore(&data_lock, flags);
1113
1114 return 0;
1115}
1116
1117void dss_ovl_get_info(struct omap_overlay *ovl,
1118 struct omap_overlay_info *info)
1119{
1120 struct ovl_priv_data *op = get_ovl_priv(ovl);
1121 unsigned long flags;
1122
1123 spin_lock_irqsave(&data_lock, flags);
1124
1125 *info = op->user_info;
1126
1127 spin_unlock_irqrestore(&data_lock, flags);
1128}
1129
1130int dss_ovl_set_manager(struct omap_overlay *ovl,
1131 struct omap_overlay_manager *mgr)
1132{
1133 struct ovl_priv_data *op = get_ovl_priv(ovl);
1134 unsigned long flags;
1135 int r;
1136
1137 if (!mgr)
1138 return -EINVAL;
1139
1140 mutex_lock(&apply_lock);
1141
1142 if (ovl->manager) {
1143 DSSERR("overlay '%s' already has a manager '%s'\n",
1144 ovl->name, ovl->manager->name);
1145 r = -EINVAL;
1146 goto err;
1147 }
1148
1149 spin_lock_irqsave(&data_lock, flags);
1150
1151 if (op->enabled) {
1152 spin_unlock_irqrestore(&data_lock, flags);
1153 DSSERR("overlay has to be disabled to change the manager\n");
1154 r = -EINVAL;
1155 goto err;
1156 }
1157
1158 op->channel = mgr->id;
1159 op->extra_info_dirty = true;
1160
1161 ovl->manager = mgr;
1162 list_add_tail(&ovl->list, &mgr->overlays);
1163
1164 spin_unlock_irqrestore(&data_lock, flags);
1165
1166 /* XXX: When there is an overlay on a DSI manual update display, and
1167 * the overlay is first disabled, then moved to tv, and enabled, we
1168 * seem to get SYNC_LOST_DIGIT error.
1169 *
1170 * Waiting doesn't seem to help, but updating the manual update display
1171 * after disabling the overlay seems to fix this. This hints that the
1172 * overlay is perhaps somehow tied to the LCD output until the output
1173 * is updated.
1174 *
1175 * Userspace workaround for this is to update the LCD after disabling
1176 * the overlay, but before moving the overlay to TV.
1177 */
1178
1179 mutex_unlock(&apply_lock);
1180
1181 return 0;
1182err:
1183 mutex_unlock(&apply_lock);
1184 return r;
1185}
1186
1187int dss_ovl_unset_manager(struct omap_overlay *ovl)
1188{
1189 struct ovl_priv_data *op = get_ovl_priv(ovl);
1190 unsigned long flags;
1191 int r;
1192
1193 mutex_lock(&apply_lock);
1194
1195 if (!ovl->manager) {
1196 DSSERR("failed to detach overlay: manager not set\n");
1197 r = -EINVAL;
1198 goto err;
1199 }
1200
1201 spin_lock_irqsave(&data_lock, flags);
1202
1203 if (op->enabled) {
1204 spin_unlock_irqrestore(&data_lock, flags);
1205 DSSERR("overlay has to be disabled to unset the manager\n");
1206 r = -EINVAL;
1207 goto err;
1208 }
1209
1210 op->channel = -1;
1211
1212 ovl->manager = NULL;
1213 list_del(&ovl->list);
1214
1215 spin_unlock_irqrestore(&data_lock, flags);
1216
1217 mutex_unlock(&apply_lock);
1218
1219 return 0;
1220err:
1221 mutex_unlock(&apply_lock);
1222 return r;
1223}
1224
1225bool dss_ovl_is_enabled(struct omap_overlay *ovl)
1226{
1227 struct ovl_priv_data *op = get_ovl_priv(ovl);
1228 unsigned long flags;
1229 bool e;
1230
1231 spin_lock_irqsave(&data_lock, flags);
1232
1233 e = op->enabled;
1234
1235 spin_unlock_irqrestore(&data_lock, flags);
1236
1237 return e;
1238}
1239
1240int dss_ovl_enable(struct omap_overlay *ovl)
1241{
1242 struct ovl_priv_data *op = get_ovl_priv(ovl);
1243 unsigned long flags;
1244 int r;
1245
1246 mutex_lock(&apply_lock);
1247
1248 if (op->enabled) {
1249 r = 0;
1250 goto err1;
1251 }
1252
1253 if (ovl->manager == NULL || ovl->manager->device == NULL) {
1254 r = -EINVAL;
1255 goto err1;
1256 }
1257
1258 spin_lock_irqsave(&data_lock, flags);
1259
1260 op->enabling = true;
1261
1262 r = dss_check_settings(ovl->manager, ovl->manager->device);
1263 if (r) {
1264 DSSERR("failed to enable overlay %d: check_settings failed\n",
1265 ovl->id);
1266 goto err2;
1267 }
1268
1269 dss_setup_fifos();
1270
1271 op->enabling = false;
1272 dss_apply_ovl_enable(ovl, true);
1273
1274 dss_write_regs();
1275 dss_set_go_bits();
1276
1277 spin_unlock_irqrestore(&data_lock, flags);
1278
1279 mutex_unlock(&apply_lock);
1280
1281 return 0;
1282err2:
1283 op->enabling = false;
1284 spin_unlock_irqrestore(&data_lock, flags);
1285err1:
1286 mutex_unlock(&apply_lock);
1287 return r;
1288}
1289
1290int dss_ovl_disable(struct omap_overlay *ovl)
1291{
1292 struct ovl_priv_data *op = get_ovl_priv(ovl);
1293 unsigned long flags;
1294 int r;
1295
1296 mutex_lock(&apply_lock);
1297
1298 if (!op->enabled) {
1299 r = 0;
1300 goto err;
1301 }
1302
1303 if (ovl->manager == NULL || ovl->manager->device == NULL) {
1304 r = -EINVAL;
1305 goto err;
1306 }
1307
1308 spin_lock_irqsave(&data_lock, flags);
1309
1310 dss_apply_ovl_enable(ovl, false);
1311 dss_write_regs();
1312 dss_set_go_bits();
1313
1314 spin_unlock_irqrestore(&data_lock, flags);
1315
1316 mutex_unlock(&apply_lock);
1317
1318 return 0;
1319
1320err:
1321 mutex_unlock(&apply_lock);
1322 return r;
1323}
1324
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index da7b18576549..8613f86fb56d 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -178,6 +178,8 @@ static int omap_dss_probe(struct platform_device *pdev)
178 178
179 dss_features_init(); 179 dss_features_init();
180 180
181 dss_apply_init();
182
181 dss_init_overlay_managers(pdev); 183 dss_init_overlay_managers(pdev);
182 dss_init_overlays(pdev); 184 dss_init_overlays(pdev);
183 185
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 5c81533eacaa..a5ec7f37c185 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -64,22 +64,6 @@ struct omap_dispc_isr_data {
64 u32 mask; 64 u32 mask;
65}; 65};
66 66
67struct dispc_h_coef {
68 s8 hc4;
69 s8 hc3;
70 u8 hc2;
71 s8 hc1;
72 s8 hc0;
73};
74
75struct dispc_v_coef {
76 s8 vc22;
77 s8 vc2;
78 u8 vc1;
79 s8 vc0;
80 s8 vc00;
81};
82
83enum omap_burst_size { 67enum omap_burst_size {
84 BURST_SIZE_X2 = 0, 68 BURST_SIZE_X2 = 0,
85 BURST_SIZE_X4 = 1, 69 BURST_SIZE_X4 = 1,
@@ -438,6 +422,34 @@ static struct omap_dss_device *dispc_mgr_get_device(enum omap_channel channel)
438 return mgr ? mgr->device : NULL; 422 return mgr ? mgr->device : NULL;
439} 423}
440 424
425u32 dispc_mgr_get_vsync_irq(enum omap_channel channel)
426{
427 switch (channel) {
428 case OMAP_DSS_CHANNEL_LCD:
429 return DISPC_IRQ_VSYNC;
430 case OMAP_DSS_CHANNEL_LCD2:
431 return DISPC_IRQ_VSYNC2;
432 case OMAP_DSS_CHANNEL_DIGIT:
433 return DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
434 default:
435 BUG();
436 }
437}
438
439u32 dispc_mgr_get_framedone_irq(enum omap_channel channel)
440{
441 switch (channel) {
442 case OMAP_DSS_CHANNEL_LCD:
443 return DISPC_IRQ_FRAMEDONE;
444 case OMAP_DSS_CHANNEL_LCD2:
445 return DISPC_IRQ_FRAMEDONE2;
446 case OMAP_DSS_CHANNEL_DIGIT:
447 return 0;
448 default:
449 BUG();
450 }
451}
452
441bool dispc_mgr_go_busy(enum omap_channel channel) 453bool dispc_mgr_go_busy(enum omap_channel channel)
442{ 454{
443 int bit; 455 int bit;
@@ -533,105 +545,27 @@ static void dispc_ovl_write_firv2_reg(enum omap_plane plane, int reg, u32 value)
533 dispc_write_reg(DISPC_OVL_FIR_COEF_V2(plane, reg), value); 545 dispc_write_reg(DISPC_OVL_FIR_COEF_V2(plane, reg), value);
534} 546}
535 547
536static void dispc_ovl_set_scale_coef(enum omap_plane plane, int hscaleup, 548static void dispc_ovl_set_scale_coef(enum omap_plane plane, int fir_hinc,
537 int vscaleup, int five_taps, 549 int fir_vinc, int five_taps,
538 enum omap_color_component color_comp) 550 enum omap_color_component color_comp)
539{ 551{
540 /* Coefficients for horizontal up-sampling */ 552 const struct dispc_coef *h_coef, *v_coef;
541 static const struct dispc_h_coef coef_hup[8] = {
542 { 0, 0, 128, 0, 0 },
543 { -1, 13, 124, -8, 0 },
544 { -2, 30, 112, -11, -1 },
545 { -5, 51, 95, -11, -2 },
546 { 0, -9, 73, 73, -9 },
547 { -2, -11, 95, 51, -5 },
548 { -1, -11, 112, 30, -2 },
549 { 0, -8, 124, 13, -1 },
550 };
551
552 /* Coefficients for vertical up-sampling */
553 static const struct dispc_v_coef coef_vup_3tap[8] = {
554 { 0, 0, 128, 0, 0 },
555 { 0, 3, 123, 2, 0 },
556 { 0, 12, 111, 5, 0 },
557 { 0, 32, 89, 7, 0 },
558 { 0, 0, 64, 64, 0 },
559 { 0, 7, 89, 32, 0 },
560 { 0, 5, 111, 12, 0 },
561 { 0, 2, 123, 3, 0 },
562 };
563
564 static const struct dispc_v_coef coef_vup_5tap[8] = {
565 { 0, 0, 128, 0, 0 },
566 { -1, 13, 124, -8, 0 },
567 { -2, 30, 112, -11, -1 },
568 { -5, 51, 95, -11, -2 },
569 { 0, -9, 73, 73, -9 },
570 { -2, -11, 95, 51, -5 },
571 { -1, -11, 112, 30, -2 },
572 { 0, -8, 124, 13, -1 },
573 };
574
575 /* Coefficients for horizontal down-sampling */
576 static const struct dispc_h_coef coef_hdown[8] = {
577 { 0, 36, 56, 36, 0 },
578 { 4, 40, 55, 31, -2 },
579 { 8, 44, 54, 27, -5 },
580 { 12, 48, 53, 22, -7 },
581 { -9, 17, 52, 51, 17 },
582 { -7, 22, 53, 48, 12 },
583 { -5, 27, 54, 44, 8 },
584 { -2, 31, 55, 40, 4 },
585 };
586
587 /* Coefficients for vertical down-sampling */
588 static const struct dispc_v_coef coef_vdown_3tap[8] = {
589 { 0, 36, 56, 36, 0 },
590 { 0, 40, 57, 31, 0 },
591 { 0, 45, 56, 27, 0 },
592 { 0, 50, 55, 23, 0 },
593 { 0, 18, 55, 55, 0 },
594 { 0, 23, 55, 50, 0 },
595 { 0, 27, 56, 45, 0 },
596 { 0, 31, 57, 40, 0 },
597 };
598
599 static const struct dispc_v_coef coef_vdown_5tap[8] = {
600 { 0, 36, 56, 36, 0 },
601 { 4, 40, 55, 31, -2 },
602 { 8, 44, 54, 27, -5 },
603 { 12, 48, 53, 22, -7 },
604 { -9, 17, 52, 51, 17 },
605 { -7, 22, 53, 48, 12 },
606 { -5, 27, 54, 44, 8 },
607 { -2, 31, 55, 40, 4 },
608 };
609
610 const struct dispc_h_coef *h_coef;
611 const struct dispc_v_coef *v_coef;
612 int i; 553 int i;
613 554
614 if (hscaleup) 555 h_coef = dispc_ovl_get_scale_coef(fir_hinc, true);
615 h_coef = coef_hup; 556 v_coef = dispc_ovl_get_scale_coef(fir_vinc, five_taps);
616 else
617 h_coef = coef_hdown;
618
619 if (vscaleup)
620 v_coef = five_taps ? coef_vup_5tap : coef_vup_3tap;
621 else
622 v_coef = five_taps ? coef_vdown_5tap : coef_vdown_3tap;
623 557
624 for (i = 0; i < 8; i++) { 558 for (i = 0; i < 8; i++) {
625 u32 h, hv; 559 u32 h, hv;
626 560
627 h = FLD_VAL(h_coef[i].hc0, 7, 0) 561 h = FLD_VAL(h_coef[i].hc0_vc00, 7, 0)
628 | FLD_VAL(h_coef[i].hc1, 15, 8) 562 | FLD_VAL(h_coef[i].hc1_vc0, 15, 8)
629 | FLD_VAL(h_coef[i].hc2, 23, 16) 563 | FLD_VAL(h_coef[i].hc2_vc1, 23, 16)
630 | FLD_VAL(h_coef[i].hc3, 31, 24); 564 | FLD_VAL(h_coef[i].hc3_vc2, 31, 24);
631 hv = FLD_VAL(h_coef[i].hc4, 7, 0) 565 hv = FLD_VAL(h_coef[i].hc4_vc22, 7, 0)
632 | FLD_VAL(v_coef[i].vc0, 15, 8) 566 | FLD_VAL(v_coef[i].hc1_vc0, 15, 8)
633 | FLD_VAL(v_coef[i].vc1, 23, 16) 567 | FLD_VAL(v_coef[i].hc2_vc1, 23, 16)
634 | FLD_VAL(v_coef[i].vc2, 31, 24); 568 | FLD_VAL(v_coef[i].hc3_vc2, 31, 24);
635 569
636 if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) { 570 if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) {
637 dispc_ovl_write_firh_reg(plane, i, h); 571 dispc_ovl_write_firh_reg(plane, i, h);
@@ -646,8 +580,8 @@ static void dispc_ovl_set_scale_coef(enum omap_plane plane, int hscaleup,
646 if (five_taps) { 580 if (five_taps) {
647 for (i = 0; i < 8; i++) { 581 for (i = 0; i < 8; i++) {
648 u32 v; 582 u32 v;
649 v = FLD_VAL(v_coef[i].vc00, 7, 0) 583 v = FLD_VAL(v_coef[i].hc0_vc00, 7, 0)
650 | FLD_VAL(v_coef[i].vc22, 15, 8); 584 | FLD_VAL(v_coef[i].hc4_vc22, 15, 8);
651 if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) 585 if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y)
652 dispc_ovl_write_firv_reg(plane, i, v); 586 dispc_ovl_write_firv_reg(plane, i, v);
653 else 587 else
@@ -875,8 +809,7 @@ static void dispc_ovl_set_color_mode(enum omap_plane plane,
875 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1); 809 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
876} 810}
877 811
878static void dispc_ovl_set_channel_out(enum omap_plane plane, 812void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel)
879 enum omap_channel channel)
880{ 813{
881 int shift; 814 int shift;
882 u32 val; 815 u32 val;
@@ -923,6 +856,39 @@ static void dispc_ovl_set_channel_out(enum omap_plane plane,
923 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); 856 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
924} 857}
925 858
859static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane)
860{
861 int shift;
862 u32 val;
863 enum omap_channel channel;
864
865 switch (plane) {
866 case OMAP_DSS_GFX:
867 shift = 8;
868 break;
869 case OMAP_DSS_VIDEO1:
870 case OMAP_DSS_VIDEO2:
871 case OMAP_DSS_VIDEO3:
872 shift = 16;
873 break;
874 default:
875 BUG();
876 }
877
878 val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
879
880 if (dss_has_feature(FEAT_MGR_LCD2)) {
881 if (FLD_GET(val, 31, 30) == 0)
882 channel = FLD_GET(val, shift, shift);
883 else
884 channel = OMAP_DSS_CHANNEL_LCD2;
885 } else {
886 channel = FLD_GET(val, shift, shift);
887 }
888
889 return channel;
890}
891
926static void dispc_ovl_set_burst_size(enum omap_plane plane, 892static void dispc_ovl_set_burst_size(enum omap_plane plane,
927 enum omap_burst_size burst_size) 893 enum omap_burst_size burst_size)
928{ 894{
@@ -964,7 +930,7 @@ void dispc_enable_gamma_table(bool enable)
964 REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9); 930 REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9);
965} 931}
966 932
967void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable) 933static void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable)
968{ 934{
969 u16 reg; 935 u16 reg;
970 936
@@ -978,7 +944,7 @@ void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable)
978 REG_FLD_MOD(reg, enable, 15, 15); 944 REG_FLD_MOD(reg, enable, 15, 15);
979} 945}
980 946
981void dispc_mgr_set_cpr_coef(enum omap_channel channel, 947static void dispc_mgr_set_cpr_coef(enum omap_channel channel,
982 struct omap_dss_cpr_coefs *coefs) 948 struct omap_dss_cpr_coefs *coefs)
983{ 949{
984 u32 coef_r, coef_g, coef_b; 950 u32 coef_r, coef_g, coef_b;
@@ -1057,8 +1023,7 @@ u32 dispc_ovl_get_fifo_size(enum omap_plane plane)
1057 return dispc.fifo_size[plane]; 1023 return dispc.fifo_size[plane];
1058} 1024}
1059 1025
1060static void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, 1026void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
1061 u32 high)
1062{ 1027{
1063 u8 hi_start, hi_end, lo_start, lo_end; 1028 u8 hi_start, hi_end, lo_start, lo_end;
1064 u32 unit; 1029 u32 unit;
@@ -1169,17 +1134,12 @@ static void dispc_ovl_set_scale_param(enum omap_plane plane,
1169 enum omap_color_component color_comp) 1134 enum omap_color_component color_comp)
1170{ 1135{
1171 int fir_hinc, fir_vinc; 1136 int fir_hinc, fir_vinc;
1172 int hscaleup, vscaleup;
1173
1174 hscaleup = orig_width <= out_width;
1175 vscaleup = orig_height <= out_height;
1176
1177 dispc_ovl_set_scale_coef(plane, hscaleup, vscaleup, five_taps,
1178 color_comp);
1179 1137
1180 fir_hinc = 1024 * orig_width / out_width; 1138 fir_hinc = 1024 * orig_width / out_width;
1181 fir_vinc = 1024 * orig_height / out_height; 1139 fir_vinc = 1024 * orig_height / out_height;
1182 1140
1141 dispc_ovl_set_scale_coef(plane, fir_hinc, fir_vinc, five_taps,
1142 color_comp);
1183 dispc_ovl_set_fir(plane, fir_hinc, fir_vinc, color_comp); 1143 dispc_ovl_set_fir(plane, fir_hinc, fir_vinc, color_comp);
1184} 1144}
1185 1145
@@ -1654,6 +1614,9 @@ static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width,
1654 u32 fclk = 0; 1614 u32 fclk = 0;
1655 u64 tmp, pclk = dispc_mgr_pclk_rate(channel); 1615 u64 tmp, pclk = dispc_mgr_pclk_rate(channel);
1656 1616
1617 if (height <= out_height && width <= out_width)
1618 return (unsigned long) pclk;
1619
1657 if (height > out_height) { 1620 if (height > out_height) {
1658 struct omap_dss_device *dssdev = dispc_mgr_get_device(channel); 1621 struct omap_dss_device *dssdev = dispc_mgr_get_device(channel);
1659 unsigned int ppl = dssdev->panel.timings.x_res; 1622 unsigned int ppl = dssdev->panel.timings.x_res;
@@ -1708,7 +1671,16 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
1708 else 1671 else
1709 vf = 1; 1672 vf = 1;
1710 1673
1711 return dispc_mgr_pclk_rate(channel) * vf * hf; 1674 if (cpu_is_omap24xx()) {
1675 if (vf > 1 && hf > 1)
1676 return dispc_mgr_pclk_rate(channel) * 4;
1677 else
1678 return dispc_mgr_pclk_rate(channel) * 2;
1679 } else if (cpu_is_omap34xx()) {
1680 return dispc_mgr_pclk_rate(channel) * vf * hf;
1681 } else {
1682 return dispc_mgr_pclk_rate(channel) * hf;
1683 }
1712} 1684}
1713 1685
1714static int dispc_ovl_calc_scaling(enum omap_plane plane, 1686static int dispc_ovl_calc_scaling(enum omap_plane plane,
@@ -1718,6 +1690,8 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
1718{ 1690{
1719 struct omap_overlay *ovl = omap_dss_get_overlay(plane); 1691 struct omap_overlay *ovl = omap_dss_get_overlay(plane);
1720 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); 1692 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
1693 const int maxsinglelinewidth =
1694 dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
1721 unsigned long fclk = 0; 1695 unsigned long fclk = 0;
1722 1696
1723 if (width == out_width && height == out_height) 1697 if (width == out_width && height == out_height)
@@ -1734,28 +1708,40 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
1734 out_height > height * 8) 1708 out_height > height * 8)
1735 return -EINVAL; 1709 return -EINVAL;
1736 1710
1737 /* Must use 5-tap filter? */ 1711 if (cpu_is_omap24xx()) {
1738 *five_taps = height > out_height * 2; 1712 if (width > maxsinglelinewidth)
1739 1713 DSSERR("Cannot scale max input width exceeded");
1740 if (!*five_taps) { 1714 *five_taps = false;
1715 fclk = calc_fclk(channel, width, height, out_width,
1716 out_height);
1717 } else if (cpu_is_omap34xx()) {
1718 if (width > (maxsinglelinewidth * 2)) {
1719 DSSERR("Cannot setup scaling");
1720 DSSERR("width exceeds maximum width possible");
1721 return -EINVAL;
1722 }
1723 fclk = calc_fclk_five_taps(channel, width, height, out_width,
1724 out_height, color_mode);
1725 if (width > maxsinglelinewidth) {
1726 if (height > out_height && height < out_height * 2)
1727 *five_taps = false;
1728 else {
1729 DSSERR("cannot setup scaling with five taps");
1730 return -EINVAL;
1731 }
1732 }
1733 if (!*five_taps)
1734 fclk = calc_fclk(channel, width, height, out_width,
1735 out_height);
1736 } else {
1737 if (width > maxsinglelinewidth) {
1738 DSSERR("Cannot scale width exceeds max line width");
1739 return -EINVAL;
1740 }
1741 fclk = calc_fclk(channel, width, height, out_width, 1741 fclk = calc_fclk(channel, width, height, out_width,
1742 out_height); 1742 out_height);
1743
1744 /* Try 5-tap filter if 3-tap fclk is too high */
1745 if (cpu_is_omap34xx() && height > out_height &&
1746 fclk > dispc_fclk_rate())
1747 *five_taps = true;
1748 }
1749
1750 if (width > (2048 >> *five_taps)) {
1751 DSSERR("failed to set up scaling, fclk too low\n");
1752 return -EINVAL;
1753 } 1743 }
1754 1744
1755 if (*five_taps)
1756 fclk = calc_fclk_five_taps(channel, width, height,
1757 out_width, out_height, color_mode);
1758
1759 DSSDBG("required fclk rate = %lu Hz\n", fclk); 1745 DSSDBG("required fclk rate = %lu Hz\n", fclk);
1760 DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate()); 1746 DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate());
1761 1747
@@ -1771,11 +1757,10 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
1771} 1757}
1772 1758
1773int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, 1759int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
1774 bool ilace, enum omap_channel channel, bool replication, 1760 bool ilace, bool replication)
1775 u32 fifo_low, u32 fifo_high)
1776{ 1761{
1777 struct omap_overlay *ovl = omap_dss_get_overlay(plane); 1762 struct omap_overlay *ovl = omap_dss_get_overlay(plane);
1778 bool five_taps = false; 1763 bool five_taps = true;
1779 bool fieldmode = 0; 1764 bool fieldmode = 0;
1780 int r, cconv = 0; 1765 int r, cconv = 0;
1781 unsigned offset0, offset1; 1766 unsigned offset0, offset1;
@@ -1783,36 +1768,43 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
1783 s32 pix_inc; 1768 s32 pix_inc;
1784 u16 frame_height = oi->height; 1769 u16 frame_height = oi->height;
1785 unsigned int field_offset = 0; 1770 unsigned int field_offset = 0;
1771 u16 outw, outh;
1772 enum omap_channel channel;
1773
1774 channel = dispc_ovl_get_channel_out(plane);
1786 1775
1787 DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> " 1776 DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> "
1788 "%dx%d, cmode %x, rot %d, mir %d, ilace %d chan %d repl %d " 1777 "%dx%d, cmode %x, rot %d, mir %d, ilace %d chan %d repl %d\n",
1789 "fifo_low %d fifo high %d\n", plane, oi->paddr, oi->p_uv_addr, 1778 plane, oi->paddr, oi->p_uv_addr,
1790 oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height, 1779 oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
1791 oi->out_width, oi->out_height, oi->color_mode, oi->rotation, 1780 oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
1792 oi->mirror, ilace, channel, replication, fifo_low, fifo_high); 1781 oi->mirror, ilace, channel, replication);
1793 1782
1794 if (oi->paddr == 0) 1783 if (oi->paddr == 0)
1795 return -EINVAL; 1784 return -EINVAL;
1796 1785
1797 if (ilace && oi->height == oi->out_height) 1786 outw = oi->out_width == 0 ? oi->width : oi->out_width;
1787 outh = oi->out_height == 0 ? oi->height : oi->out_height;
1788
1789 if (ilace && oi->height == outh)
1798 fieldmode = 1; 1790 fieldmode = 1;
1799 1791
1800 if (ilace) { 1792 if (ilace) {
1801 if (fieldmode) 1793 if (fieldmode)
1802 oi->height /= 2; 1794 oi->height /= 2;
1803 oi->pos_y /= 2; 1795 oi->pos_y /= 2;
1804 oi->out_height /= 2; 1796 outh /= 2;
1805 1797
1806 DSSDBG("adjusting for ilace: height %d, pos_y %d, " 1798 DSSDBG("adjusting for ilace: height %d, pos_y %d, "
1807 "out_height %d\n", 1799 "out_height %d\n",
1808 oi->height, oi->pos_y, oi->out_height); 1800 oi->height, oi->pos_y, outh);
1809 } 1801 }
1810 1802
1811 if (!dss_feat_color_mode_supported(plane, oi->color_mode)) 1803 if (!dss_feat_color_mode_supported(plane, oi->color_mode))
1812 return -EINVAL; 1804 return -EINVAL;
1813 1805
1814 r = dispc_ovl_calc_scaling(plane, channel, oi->width, oi->height, 1806 r = dispc_ovl_calc_scaling(plane, channel, oi->width, oi->height,
1815 oi->out_width, oi->out_height, oi->color_mode, 1807 outw, outh, oi->color_mode,
1816 &five_taps); 1808 &five_taps);
1817 if (r) 1809 if (r)
1818 return r; 1810 return r;
@@ -1830,10 +1822,10 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
1830 * so the integer part must be added to the base address of the 1822 * so the integer part must be added to the base address of the
1831 * bottom field. 1823 * bottom field.
1832 */ 1824 */
1833 if (!oi->height || oi->height == oi->out_height) 1825 if (!oi->height || oi->height == outh)
1834 field_offset = 0; 1826 field_offset = 0;
1835 else 1827 else
1836 field_offset = oi->height / oi->out_height / 2; 1828 field_offset = oi->height / outh / 2;
1837 } 1829 }
1838 1830
1839 /* Fields are independent but interleaved in memory. */ 1831 /* Fields are independent but interleaved in memory. */
@@ -1869,7 +1861,7 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
1869 dispc_ovl_set_pix_inc(plane, pix_inc); 1861 dispc_ovl_set_pix_inc(plane, pix_inc);
1870 1862
1871 DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, oi->width, 1863 DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, oi->width,
1872 oi->height, oi->out_width, oi->out_height); 1864 oi->height, outw, outh);
1873 1865
1874 dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y); 1866 dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y);
1875 1867
@@ -1877,10 +1869,10 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
1877 1869
1878 if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) { 1870 if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) {
1879 dispc_ovl_set_scaling(plane, oi->width, oi->height, 1871 dispc_ovl_set_scaling(plane, oi->width, oi->height,
1880 oi->out_width, oi->out_height, 1872 outw, outh,
1881 ilace, five_taps, fieldmode, 1873 ilace, five_taps, fieldmode,
1882 oi->color_mode, oi->rotation); 1874 oi->color_mode, oi->rotation);
1883 dispc_ovl_set_vid_size(plane, oi->out_width, oi->out_height); 1875 dispc_ovl_set_vid_size(plane, outw, outh);
1884 dispc_ovl_set_vid_color_conv(plane, cconv); 1876 dispc_ovl_set_vid_color_conv(plane, cconv);
1885 } 1877 }
1886 1878
@@ -1891,10 +1883,7 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
1891 dispc_ovl_set_pre_mult_alpha(plane, oi->pre_mult_alpha); 1883 dispc_ovl_set_pre_mult_alpha(plane, oi->pre_mult_alpha);
1892 dispc_ovl_setup_global_alpha(plane, oi->global_alpha); 1884 dispc_ovl_setup_global_alpha(plane, oi->global_alpha);
1893 1885
1894 dispc_ovl_set_channel_out(plane, channel);
1895
1896 dispc_ovl_enable_replication(plane, replication); 1886 dispc_ovl_enable_replication(plane, replication);
1897 dispc_ovl_set_fifo_threshold(plane, fifo_low, fifo_high);
1898 1887
1899 return 0; 1888 return 0;
1900} 1889}
@@ -1916,10 +1905,14 @@ static void dispc_disable_isr(void *data, u32 mask)
1916 1905
1917static void _enable_lcd_out(enum omap_channel channel, bool enable) 1906static void _enable_lcd_out(enum omap_channel channel, bool enable)
1918{ 1907{
1919 if (channel == OMAP_DSS_CHANNEL_LCD2) 1908 if (channel == OMAP_DSS_CHANNEL_LCD2) {
1920 REG_FLD_MOD(DISPC_CONTROL2, enable ? 1 : 0, 0, 0); 1909 REG_FLD_MOD(DISPC_CONTROL2, enable ? 1 : 0, 0, 0);
1921 else 1910 /* flush posted write */
1911 dispc_read_reg(DISPC_CONTROL2);
1912 } else {
1922 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0); 1913 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0);
1914 dispc_read_reg(DISPC_CONTROL);
1915 }
1923} 1916}
1924 1917
1925static void dispc_mgr_enable_lcd_out(enum omap_channel channel, bool enable) 1918static void dispc_mgr_enable_lcd_out(enum omap_channel channel, bool enable)
@@ -1967,6 +1960,8 @@ static void dispc_mgr_enable_lcd_out(enum omap_channel channel, bool enable)
1967static void _enable_digit_out(bool enable) 1960static void _enable_digit_out(bool enable)
1968{ 1961{
1969 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1); 1962 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1);
1963 /* flush posted write */
1964 dispc_read_reg(DISPC_CONTROL);
1970} 1965}
1971 1966
1972static void dispc_mgr_enable_digit_out(bool enable) 1967static void dispc_mgr_enable_digit_out(bool enable)
@@ -2124,25 +2119,12 @@ void dispc_set_loadmode(enum omap_dss_load_mode mode)
2124} 2119}
2125 2120
2126 2121
2127void dispc_mgr_set_default_color(enum omap_channel channel, u32 color) 2122static void dispc_mgr_set_default_color(enum omap_channel channel, u32 color)
2128{ 2123{
2129 dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color); 2124 dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color);
2130} 2125}
2131 2126
2132u32 dispc_mgr_get_default_color(enum omap_channel channel) 2127static void dispc_mgr_set_trans_key(enum omap_channel ch,
2133{
2134 u32 l;
2135
2136 BUG_ON(channel != OMAP_DSS_CHANNEL_DIGIT &&
2137 channel != OMAP_DSS_CHANNEL_LCD &&
2138 channel != OMAP_DSS_CHANNEL_LCD2);
2139
2140 l = dispc_read_reg(DISPC_DEFAULT_COLOR(channel));
2141
2142 return l;
2143}
2144
2145void dispc_mgr_set_trans_key(enum omap_channel ch,
2146 enum omap_dss_trans_key_type type, 2128 enum omap_dss_trans_key_type type,
2147 u32 trans_key) 2129 u32 trans_key)
2148{ 2130{
@@ -2156,26 +2138,7 @@ void dispc_mgr_set_trans_key(enum omap_channel ch,
2156 dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key); 2138 dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key);
2157} 2139}
2158 2140
2159void dispc_mgr_get_trans_key(enum omap_channel ch, 2141static void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable)
2160 enum omap_dss_trans_key_type *type,
2161 u32 *trans_key)
2162{
2163 if (type) {
2164 if (ch == OMAP_DSS_CHANNEL_LCD)
2165 *type = REG_GET(DISPC_CONFIG, 11, 11);
2166 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
2167 *type = REG_GET(DISPC_CONFIG, 13, 13);
2168 else if (ch == OMAP_DSS_CHANNEL_LCD2)
2169 *type = REG_GET(DISPC_CONFIG2, 11, 11);
2170 else
2171 BUG();
2172 }
2173
2174 if (trans_key)
2175 *trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch));
2176}
2177
2178void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable)
2179{ 2142{
2180 if (ch == OMAP_DSS_CHANNEL_LCD) 2143 if (ch == OMAP_DSS_CHANNEL_LCD)
2181 REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10); 2144 REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
@@ -2185,7 +2148,8 @@ void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable)
2185 REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10); 2148 REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10);
2186} 2149}
2187 2150
2188void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable) 2151static void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch,
2152 bool enable)
2189{ 2153{
2190 if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) 2154 if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
2191 return; 2155 return;
@@ -2196,40 +2160,20 @@ void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable)
2196 REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19); 2160 REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
2197} 2161}
2198 2162
2199bool dispc_mgr_alpha_fixed_zorder_enabled(enum omap_channel ch) 2163void dispc_mgr_setup(enum omap_channel channel,
2200{ 2164 struct omap_overlay_manager_info *info)
2201 bool enabled;
2202
2203 if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
2204 return false;
2205
2206 if (ch == OMAP_DSS_CHANNEL_LCD)
2207 enabled = REG_GET(DISPC_CONFIG, 18, 18);
2208 else if (ch == OMAP_DSS_CHANNEL_DIGIT)
2209 enabled = REG_GET(DISPC_CONFIG, 19, 19);
2210 else
2211 BUG();
2212
2213 return enabled;
2214}
2215
2216bool dispc_mgr_trans_key_enabled(enum omap_channel ch)
2217{ 2165{
2218 bool enabled; 2166 dispc_mgr_set_default_color(channel, info->default_color);
2219 2167 dispc_mgr_set_trans_key(channel, info->trans_key_type, info->trans_key);
2220 if (ch == OMAP_DSS_CHANNEL_LCD) 2168 dispc_mgr_enable_trans_key(channel, info->trans_enabled);
2221 enabled = REG_GET(DISPC_CONFIG, 10, 10); 2169 dispc_mgr_enable_alpha_fixed_zorder(channel,
2222 else if (ch == OMAP_DSS_CHANNEL_DIGIT) 2170 info->partial_alpha_enabled);
2223 enabled = REG_GET(DISPC_CONFIG, 12, 12); 2171 if (dss_has_feature(FEAT_CPR)) {
2224 else if (ch == OMAP_DSS_CHANNEL_LCD2) 2172 dispc_mgr_enable_cpr(channel, info->cpr_enable);
2225 enabled = REG_GET(DISPC_CONFIG2, 10, 10); 2173 dispc_mgr_set_cpr_coef(channel, &info->cpr_coefs);
2226 else 2174 }
2227 BUG();
2228
2229 return enabled;
2230} 2175}
2231 2176
2232
2233void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines) 2177void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
2234{ 2178{
2235 int code; 2179 int code;
@@ -3184,7 +3128,8 @@ static void dispc_error_worker(struct work_struct *work)
3184 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { 3128 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
3185 struct omap_overlay_manager *mgr; 3129 struct omap_overlay_manager *mgr;
3186 mgr = omap_dss_get_overlay_manager(i); 3130 mgr = omap_dss_get_overlay_manager(i);
3187 mgr->device->driver->disable(mgr->device); 3131 if (mgr->device && mgr->device->driver)
3132 mgr->device->driver->disable(mgr->device);
3188 } 3133 }
3189 } 3134 }
3190 3135
diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/omap2/dss/dispc.h
index c06efc38983e..5836bd1650f9 100644
--- a/drivers/video/omap2/dss/dispc.h
+++ b/drivers/video/omap2/dss/dispc.h
@@ -97,6 +97,17 @@
97#define DISPC_OVL_PRELOAD(n) (DISPC_OVL_BASE(n) + \ 97#define DISPC_OVL_PRELOAD(n) (DISPC_OVL_BASE(n) + \
98 DISPC_PRELOAD_OFFSET(n)) 98 DISPC_PRELOAD_OFFSET(n))
99 99
100/* DISPC up/downsampling FIR filter coefficient structure */
101struct dispc_coef {
102 s8 hc4_vc22;
103 s8 hc3_vc2;
104 u8 hc2_vc1;
105 s8 hc1_vc0;
106 s8 hc0_vc00;
107};
108
109const struct dispc_coef *dispc_ovl_get_scale_coef(int inc, int five_taps);
110
100/* DISPC manager/channel specific registers */ 111/* DISPC manager/channel specific registers */
101static inline u16 DISPC_DEFAULT_COLOR(enum omap_channel channel) 112static inline u16 DISPC_DEFAULT_COLOR(enum omap_channel channel)
102{ 113{
diff --git a/drivers/video/omap2/dss/dispc_coefs.c b/drivers/video/omap2/dss/dispc_coefs.c
new file mode 100644
index 000000000000..069bccbb3f12
--- /dev/null
+++ b/drivers/video/omap2/dss/dispc_coefs.c
@@ -0,0 +1,326 @@
1/*
2 * linux/drivers/video/omap2/dss/dispc_coefs.c
3 *
4 * Copyright (C) 2011 Texas Instruments
5 * Author: Chandrabhanu Mahapatra <cmahapatra@ti.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <linux/kernel.h>
21#include <video/omapdss.h>
22#include "dispc.h"
23
24#define ARRAY_LEN(array) (sizeof(array) / sizeof(array[0]))
25
26static const struct dispc_coef coef3_M8[8] = {
27 { 0, 0, 128, 0, 0 },
28 { 0, -4, 123, 9, 0 },
29 { 0, -4, 108, 87, 0 },
30 { 0, -2, 87, 43, 0 },
31 { 0, 64, 64, 0, 0 },
32 { 0, 43, 87, -2, 0 },
33 { 0, 24, 108, -4, 0 },
34 { 0, 9, 123, -4, 0 },
35};
36
37static const struct dispc_coef coef3_M9[8] = {
38 { 0, 6, 116, 6, 0 },
39 { 0, 0, 112, 16, 0 },
40 { 0, -2, 100, 30, 0 },
41 { 0, -2, 83, 47, 0 },
42 { 0, 64, 64, 0, 0 },
43 { 0, 47, 83, -2, 0 },
44 { 0, 30, 100, -2, 0 },
45 { 0, 16, 112, 0, 0 },
46};
47
48static const struct dispc_coef coef3_M10[8] = {
49 { 0, 10, 108, 10, 0 },
50 { 0, 3, 104, 21, 0 },
51 { 0, 0, 94, 34, 0 },
52 { 0, -1, 80, 49, 0 },
53 { 0, 64, 64, 0, 0 },
54 { 0, 49, 80, -1, 0 },
55 { 0, 34, 94, 0, 0 },
56 { 0, 21, 104, 3, 0 },
57};
58
59static const struct dispc_coef coef3_M11[8] = {
60 { 0, 14, 100, 14, 0 },
61 { 0, 6, 98, 24, 0 },
62 { 0, 2, 90, 36, 0 },
63 { 0, 0, 78, 50, 0 },
64 { 0, 64, 64, 0, 0 },
65 { 0, 50, 78, 0, 0 },
66 { 0, 36, 90, 2, 0 },
67 { 0, 24, 98, 6, 0 },
68};
69
70static const struct dispc_coef coef3_M12[8] = {
71 { 0, 16, 96, 16, 0 },
72 { 0, 9, 93, 26, 0 },
73 { 0, 4, 86, 38, 0 },
74 { 0, 1, 76, 51, 0 },
75 { 0, 64, 64, 0, 0 },
76 { 0, 51, 76, 1, 0 },
77 { 0, 38, 86, 4, 0 },
78 { 0, 26, 93, 9, 0 },
79};
80
81static const struct dispc_coef coef3_M13[8] = {
82 { 0, 18, 92, 18, 0 },
83 { 0, 10, 90, 28, 0 },
84 { 0, 5, 83, 40, 0 },
85 { 0, 1, 75, 52, 0 },
86 { 0, 64, 64, 0, 0 },
87 { 0, 52, 75, 1, 0 },
88 { 0, 40, 83, 5, 0 },
89 { 0, 28, 90, 10, 0 },
90};
91
92static const struct dispc_coef coef3_M14[8] = {
93 { 0, 20, 88, 20, 0 },
94 { 0, 12, 86, 30, 0 },
95 { 0, 6, 81, 41, 0 },
96 { 0, 2, 74, 52, 0 },
97 { 0, 64, 64, 0, 0 },
98 { 0, 52, 74, 2, 0 },
99 { 0, 41, 81, 6, 0 },
100 { 0, 30, 86, 12, 0 },
101};
102
103static const struct dispc_coef coef3_M16[8] = {
104 { 0, 22, 84, 22, 0 },
105 { 0, 14, 82, 32, 0 },
106 { 0, 8, 78, 42, 0 },
107 { 0, 3, 72, 53, 0 },
108 { 0, 64, 64, 0, 0 },
109 { 0, 53, 72, 3, 0 },
110 { 0, 42, 78, 8, 0 },
111 { 0, 32, 82, 14, 0 },
112};
113
114static const struct dispc_coef coef3_M19[8] = {
115 { 0, 24, 80, 24, 0 },
116 { 0, 16, 79, 33, 0 },
117 { 0, 9, 76, 43, 0 },
118 { 0, 4, 70, 54, 0 },
119 { 0, 64, 64, 0, 0 },
120 { 0, 54, 70, 4, 0 },
121 { 0, 43, 76, 9, 0 },
122 { 0, 33, 79, 16, 0 },
123};
124
125static const struct dispc_coef coef3_M22[8] = {
126 { 0, 25, 78, 25, 0 },
127 { 0, 17, 77, 34, 0 },
128 { 0, 10, 74, 44, 0 },
129 { 0, 5, 69, 54, 0 },
130 { 0, 64, 64, 0, 0 },
131 { 0, 54, 69, 5, 0 },
132 { 0, 44, 74, 10, 0 },
133 { 0, 34, 77, 17, 0 },
134};
135
136static const struct dispc_coef coef3_M26[8] = {
137 { 0, 26, 76, 26, 0 },
138 { 0, 19, 74, 35, 0 },
139 { 0, 11, 72, 45, 0 },
140 { 0, 5, 69, 54, 0 },
141 { 0, 64, 64, 0, 0 },
142 { 0, 54, 69, 5, 0 },
143 { 0, 45, 72, 11, 0 },
144 { 0, 35, 74, 19, 0 },
145};
146
147static const struct dispc_coef coef3_M32[8] = {
148 { 0, 27, 74, 27, 0 },
149 { 0, 19, 73, 36, 0 },
150 { 0, 12, 71, 45, 0 },
151 { 0, 6, 68, 54, 0 },
152 { 0, 64, 64, 0, 0 },
153 { 0, 54, 68, 6, 0 },
154 { 0, 45, 71, 12, 0 },
155 { 0, 36, 73, 19, 0 },
156};
157
158static const struct dispc_coef coef5_M8[8] = {
159 { 0, 0, 128, 0, 0 },
160 { -2, 14, 125, -10, 1 },
161 { -6, 33, 114, -15, 2 },
162 { -10, 55, 98, -16, 1 },
163 { 0, -14, 78, 78, -14 },
164 { 1, -16, 98, 55, -10 },
165 { 2, -15, 114, 33, -6 },
166 { 1, -10, 125, 14, -2 },
167};
168
169static const struct dispc_coef coef5_M9[8] = {
170 { -3, 10, 114, 10, -3 },
171 { -6, 24, 110, 0, -1 },
172 { -8, 40, 103, -7, 0 },
173 { -11, 58, 91, -11, 1 },
174 { 0, -12, 76, 76, -12 },
175 { 1, -11, 91, 58, -11 },
176 { 0, -7, 103, 40, -8 },
177 { -1, 0, 111, 24, -6 },
178};
179
180static const struct dispc_coef coef5_M10[8] = {
181 { -4, 18, 100, 18, -4 },
182 { -6, 30, 99, 8, -3 },
183 { -8, 44, 93, 0, -1 },
184 { -9, 58, 84, -5, 0 },
185 { 0, -8, 72, 72, -8 },
186 { 0, -5, 84, 58, -9 },
187 { -1, 0, 93, 44, -8 },
188 { -3, 8, 99, 30, -6 },
189};
190
191static const struct dispc_coef coef5_M11[8] = {
192 { -5, 23, 92, 23, -5 },
193 { -6, 34, 90, 13, -3 },
194 { -6, 45, 85, 6, -2 },
195 { -6, 57, 78, 0, -1 },
196 { 0, -4, 68, 68, -4 },
197 { -1, 0, 78, 57, -6 },
198 { -2, 6, 85, 45, -6 },
199 { -3, 13, 90, 34, -6 },
200};
201
202static const struct dispc_coef coef5_M12[8] = {
203 { -4, 26, 84, 26, -4 },
204 { -5, 36, 82, 18, -3 },
205 { -4, 46, 78, 10, -2 },
206 { -3, 55, 72, 5, -1 },
207 { 0, 0, 64, 64, 0 },
208 { -1, 5, 72, 55, -3 },
209 { -2, 10, 78, 46, -4 },
210 { -3, 18, 82, 36, -5 },
211};
212
213static const struct dispc_coef coef5_M13[8] = {
214 { -3, 28, 78, 28, -3 },
215 { -3, 37, 76, 21, -3 },
216 { -2, 45, 73, 14, -2 },
217 { 0, 53, 68, 8, -1 },
218 { 0, 3, 61, 61, 3 },
219 { -1, 8, 68, 53, 0 },
220 { -2, 14, 73, 45, -2 },
221 { -3, 21, 76, 37, -3 },
222};
223
224static const struct dispc_coef coef5_M14[8] = {
225 { -2, 30, 72, 30, -2 },
226 { -1, 37, 71, 23, -2 },
227 { 0, 45, 69, 16, -2 },
228 { 3, 52, 64, 10, -1 },
229 { 0, 6, 58, 58, 6 },
230 { -1, 10, 64, 52, 3 },
231 { -2, 16, 69, 45, 0 },
232 { -2, 23, 71, 37, -1 },
233};
234
235static const struct dispc_coef coef5_M16[8] = {
236 { 0, 31, 66, 31, 0 },
237 { 1, 38, 65, 25, -1 },
238 { 3, 44, 62, 20, -1 },
239 { 6, 49, 59, 14, 0 },
240 { 0, 10, 54, 54, 10 },
241 { 0, 14, 59, 49, 6 },
242 { -1, 20, 62, 44, 3 },
243 { -1, 25, 65, 38, 1 },
244};
245
246static const struct dispc_coef coef5_M19[8] = {
247 { 3, 32, 58, 32, 3 },
248 { 4, 38, 58, 27, 1 },
249 { 7, 42, 55, 23, 1 },
250 { 10, 46, 54, 18, 0 },
251 { 0, 14, 50, 50, 14 },
252 { 0, 18, 54, 46, 10 },
253 { 1, 23, 55, 42, 7 },
254 { 1, 27, 58, 38, 4 },
255};
256
257static const struct dispc_coef coef5_M22[8] = {
258 { 4, 33, 54, 33, 4 },
259 { 6, 37, 54, 28, 3 },
260 { 9, 41, 53, 24, 1 },
261 { 12, 45, 51, 20, 0 },
262 { 0, 16, 48, 48, 16 },
263 { 0, 20, 51, 45, 12 },
264 { 1, 24, 53, 41, 9 },
265 { 3, 28, 54, 37, 6 },
266};
267
268static const struct dispc_coef coef5_M26[8] = {
269 { 6, 33, 50, 33, 6 },
270 { 8, 36, 51, 29, 4 },
271 { 11, 40, 50, 25, 2 },
272 { 14, 43, 48, 22, 1 },
273 { 0, 18, 46, 46, 18 },
274 { 1, 22, 48, 43, 14 },
275 { 2, 25, 50, 40, 11 },
276 { 4, 29, 51, 36, 8 },
277};
278
279static const struct dispc_coef coef5_M32[8] = {
280 { 7, 33, 48, 33, 7 },
281 { 10, 36, 48, 29, 5 },
282 { 13, 39, 47, 26, 3 },
283 { 16, 42, 46, 23, 1 },
284 { 0, 19, 45, 45, 19 },
285 { 1, 23, 46, 42, 16 },
286 { 3, 26, 47, 39, 13 },
287 { 5, 29, 48, 36, 10 },
288};
289
290const struct dispc_coef *dispc_ovl_get_scale_coef(int inc, int five_taps)
291{
292 int i;
293 static const struct {
294 int Mmin;
295 int Mmax;
296 const struct dispc_coef *coef_3;
297 const struct dispc_coef *coef_5;
298 } coefs[] = {
299 { 27, 32, coef3_M32, coef5_M32 },
300 { 23, 26, coef3_M26, coef5_M26 },
301 { 20, 22, coef3_M22, coef5_M22 },
302 { 17, 19, coef3_M19, coef5_M19 },
303 { 15, 16, coef3_M16, coef5_M16 },
304 { 14, 14, coef3_M14, coef5_M14 },
305 { 13, 13, coef3_M13, coef5_M13 },
306 { 12, 12, coef3_M12, coef5_M12 },
307 { 11, 11, coef3_M11, coef5_M11 },
308 { 10, 10, coef3_M10, coef5_M10 },
309 { 9, 9, coef3_M9, coef5_M9 },
310 { 4, 8, coef3_M8, coef5_M8 },
311 /*
312 * When upscaling more than two times, blockiness and outlines
313 * around the image are observed when M8 tables are used. M11,
314 * M16 and M19 tables are used to prevent this.
315 */
316 { 3, 3, coef3_M11, coef5_M11 },
317 { 2, 2, coef3_M16, coef5_M16 },
318 { 0, 1, coef3_M19, coef5_M19 },
319 };
320
321 inc /= 128;
322 for (i = 0; i < ARRAY_LEN(coefs); ++i)
323 if (inc >= coefs[i].Mmin && inc <= coefs[i].Mmax)
324 return five_taps ? coefs[i].coef_5 : coefs[i].coef_3;
325 return NULL;
326}
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 976ac23dcd0c..395d658a94fc 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -223,10 +223,13 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
223 223
224 mdelay(2); 224 mdelay(2);
225 225
226 dssdev->manager->enable(dssdev->manager); 226 r = dss_mgr_enable(dssdev->manager);
227 if (r)
228 goto err_mgr_enable;
227 229
228 return 0; 230 return 0;
229 231
232err_mgr_enable:
230err_set_mode: 233err_set_mode:
231 if (dpi_use_dsi_pll(dssdev)) 234 if (dpi_use_dsi_pll(dssdev))
232 dsi_pll_uninit(dpi.dsidev, true); 235 dsi_pll_uninit(dpi.dsidev, true);
@@ -249,7 +252,7 @@ EXPORT_SYMBOL(omapdss_dpi_display_enable);
249 252
250void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) 253void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
251{ 254{
252 dssdev->manager->disable(dssdev->manager); 255 dss_mgr_disable(dssdev->manager);
253 256
254 if (dpi_use_dsi_pll(dssdev)) { 257 if (dpi_use_dsi_pll(dssdev)) {
255 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); 258 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index 46f37883e499..d4d676c82c12 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -203,6 +203,21 @@ struct dsi_reg { u16 idx; };
203typedef void (*omap_dsi_isr_t) (void *arg, u32 mask); 203typedef void (*omap_dsi_isr_t) (void *arg, u32 mask);
204 204
205#define DSI_MAX_NR_ISRS 2 205#define DSI_MAX_NR_ISRS 2
206#define DSI_MAX_NR_LANES 5
207
208enum dsi_lane_function {
209 DSI_LANE_UNUSED = 0,
210 DSI_LANE_CLK,
211 DSI_LANE_DATA1,
212 DSI_LANE_DATA2,
213 DSI_LANE_DATA3,
214 DSI_LANE_DATA4,
215};
216
217struct dsi_lane_config {
218 enum dsi_lane_function function;
219 u8 polarity;
220};
206 221
207struct dsi_isr_data { 222struct dsi_isr_data {
208 omap_dsi_isr_t isr; 223 omap_dsi_isr_t isr;
@@ -223,24 +238,6 @@ enum dsi_vc_source {
223 DSI_VC_SOURCE_VP, 238 DSI_VC_SOURCE_VP,
224}; 239};
225 240
226enum dsi_lane {
227 DSI_CLK_P = 1 << 0,
228 DSI_CLK_N = 1 << 1,
229 DSI_DATA1_P = 1 << 2,
230 DSI_DATA1_N = 1 << 3,
231 DSI_DATA2_P = 1 << 4,
232 DSI_DATA2_N = 1 << 5,
233 DSI_DATA3_P = 1 << 6,
234 DSI_DATA3_N = 1 << 7,
235 DSI_DATA4_P = 1 << 8,
236 DSI_DATA4_N = 1 << 9,
237};
238
239struct dsi_update_region {
240 u16 x, y, w, h;
241 struct omap_dss_device *device;
242};
243
244struct dsi_irq_stats { 241struct dsi_irq_stats {
245 unsigned long last_reset; 242 unsigned long last_reset;
246 unsigned irq_count; 243 unsigned irq_count;
@@ -290,7 +287,9 @@ struct dsi_data {
290 struct dsi_isr_tables isr_tables_copy; 287 struct dsi_isr_tables isr_tables_copy;
291 288
292 int update_channel; 289 int update_channel;
293 struct dsi_update_region update_region; 290#ifdef DEBUG
291 unsigned update_bytes;
292#endif
294 293
295 bool te_enabled; 294 bool te_enabled;
296 bool ulps_enabled; 295 bool ulps_enabled;
@@ -327,7 +326,10 @@ struct dsi_data {
327 unsigned long fint_min, fint_max; 326 unsigned long fint_min, fint_max;
328 unsigned long lpdiv_max; 327 unsigned long lpdiv_max;
329 328
330 int num_data_lanes; 329 unsigned num_lanes_supported;
330
331 struct dsi_lane_config lanes[DSI_MAX_NR_LANES];
332 unsigned num_lanes_used;
331 333
332 unsigned scp_clk_refcount; 334 unsigned scp_clk_refcount;
333}; 335};
@@ -413,14 +415,29 @@ static void dsi_completion_handler(void *data, u32 mask)
413static inline int wait_for_bit_change(struct platform_device *dsidev, 415static inline int wait_for_bit_change(struct platform_device *dsidev,
414 const struct dsi_reg idx, int bitnum, int value) 416 const struct dsi_reg idx, int bitnum, int value)
415{ 417{
416 int t = 100000; 418 unsigned long timeout;
419 ktime_t wait;
420 int t;
417 421
418 while (REG_GET(dsidev, idx, bitnum, bitnum) != value) { 422 /* first busyloop to see if the bit changes right away */
419 if (--t == 0) 423 t = 100;
420 return !value; 424 while (t-- > 0) {
425 if (REG_GET(dsidev, idx, bitnum, bitnum) == value)
426 return value;
421 } 427 }
422 428
423 return value; 429 /* then loop for 500ms, sleeping for 1ms in between */
430 timeout = jiffies + msecs_to_jiffies(500);
431 while (time_before(jiffies, timeout)) {
432 if (REG_GET(dsidev, idx, bitnum, bitnum) == value)
433 return value;
434
435 wait = ns_to_ktime(1000 * 1000);
436 set_current_state(TASK_UNINTERRUPTIBLE);
437 schedule_hrtimeout(&wait, HRTIMER_MODE_REL);
438 }
439
440 return !value;
424} 441}
425 442
426u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt) 443u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt)
@@ -454,7 +471,6 @@ static void dsi_perf_mark_start(struct platform_device *dsidev)
454static void dsi_perf_show(struct platform_device *dsidev, const char *name) 471static void dsi_perf_show(struct platform_device *dsidev, const char *name)
455{ 472{
456 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 473 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
457 struct omap_dss_device *dssdev = dsi->update_region.device;
458 ktime_t t, setup_time, trans_time; 474 ktime_t t, setup_time, trans_time;
459 u32 total_bytes; 475 u32 total_bytes;
460 u32 setup_us, trans_us, total_us; 476 u32 setup_us, trans_us, total_us;
@@ -476,9 +492,7 @@ static void dsi_perf_show(struct platform_device *dsidev, const char *name)
476 492
477 total_us = setup_us + trans_us; 493 total_us = setup_us + trans_us;
478 494
479 total_bytes = dsi->update_region.w * 495 total_bytes = dsi->update_bytes;
480 dsi->update_region.h *
481 dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8;
482 496
483 printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), " 497 printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), "
484 "%u bytes, %u kbytes/sec\n", 498 "%u bytes, %u kbytes/sec\n",
@@ -1720,17 +1734,19 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
1720 seq_printf(s, "CLKIN4DDR\t%-16luregm %u\n", 1734 seq_printf(s, "CLKIN4DDR\t%-16luregm %u\n",
1721 cinfo->clkin4ddr, cinfo->regm); 1735 cinfo->clkin4ddr, cinfo->regm);
1722 1736
1723 seq_printf(s, "%s (%s)\t%-16luregm_dispc %u\t(%s)\n", 1737 seq_printf(s, "DSI_PLL_HSDIV_DISPC (%s)\t%-16luregm_dispc %u\t(%s)\n",
1724 dss_get_generic_clk_source_name(dispc_clk_src), 1738 dss_feat_get_clk_source_name(dsi_module == 0 ?
1725 dss_feat_get_clk_source_name(dispc_clk_src), 1739 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC :
1740 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC),
1726 cinfo->dsi_pll_hsdiv_dispc_clk, 1741 cinfo->dsi_pll_hsdiv_dispc_clk,
1727 cinfo->regm_dispc, 1742 cinfo->regm_dispc,
1728 dispc_clk_src == OMAP_DSS_CLK_SRC_FCK ? 1743 dispc_clk_src == OMAP_DSS_CLK_SRC_FCK ?
1729 "off" : "on"); 1744 "off" : "on");
1730 1745
1731 seq_printf(s, "%s (%s)\t%-16luregm_dsi %u\t(%s)\n", 1746 seq_printf(s, "DSI_PLL_HSDIV_DSI (%s)\t%-16luregm_dsi %u\t(%s)\n",
1732 dss_get_generic_clk_source_name(dsi_clk_src), 1747 dss_feat_get_clk_source_name(dsi_module == 0 ?
1733 dss_feat_get_clk_source_name(dsi_clk_src), 1748 OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
1749 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI),
1734 cinfo->dsi_pll_hsdiv_dsi_clk, 1750 cinfo->dsi_pll_hsdiv_dsi_clk,
1735 cinfo->regm_dsi, 1751 cinfo->regm_dsi,
1736 dsi_clk_src == OMAP_DSS_CLK_SRC_FCK ? 1752 dsi_clk_src == OMAP_DSS_CLK_SRC_FCK ?
@@ -2029,34 +2045,6 @@ static int dsi_cio_power(struct platform_device *dsidev,
2029 return 0; 2045 return 0;
2030} 2046}
2031 2047
2032/* Number of data lanes present on DSI interface */
2033static inline int dsi_get_num_data_lanes(struct platform_device *dsidev)
2034{
2035 /* DSI on OMAP3 doesn't have register DSI_GNQ, set number
2036 * of data lanes as 2 by default */
2037 if (dss_has_feature(FEAT_DSI_GNQ))
2038 return REG_GET(dsidev, DSI_GNQ, 11, 9); /* NB_DATA_LANES */
2039 else
2040 return 2;
2041}
2042
2043/* Number of data lanes used by the dss device */
2044static inline int dsi_get_num_data_lanes_dssdev(struct omap_dss_device *dssdev)
2045{
2046 int num_data_lanes = 0;
2047
2048 if (dssdev->phy.dsi.data1_lane != 0)
2049 num_data_lanes++;
2050 if (dssdev->phy.dsi.data2_lane != 0)
2051 num_data_lanes++;
2052 if (dssdev->phy.dsi.data3_lane != 0)
2053 num_data_lanes++;
2054 if (dssdev->phy.dsi.data4_lane != 0)
2055 num_data_lanes++;
2056
2057 return num_data_lanes;
2058}
2059
2060static unsigned dsi_get_line_buf_size(struct platform_device *dsidev) 2048static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)
2061{ 2049{
2062 int val; 2050 int val;
@@ -2088,59 +2076,112 @@ static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)
2088 } 2076 }
2089} 2077}
2090 2078
2091static void dsi_set_lane_config(struct omap_dss_device *dssdev) 2079static int dsi_parse_lane_config(struct omap_dss_device *dssdev)
2092{ 2080{
2093 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 2081 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2094 u32 r; 2082 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2095 int num_data_lanes_dssdev = dsi_get_num_data_lanes_dssdev(dssdev); 2083 u8 lanes[DSI_MAX_NR_LANES];
2084 u8 polarities[DSI_MAX_NR_LANES];
2085 int num_lanes, i;
2086
2087 static const enum dsi_lane_function functions[] = {
2088 DSI_LANE_CLK,
2089 DSI_LANE_DATA1,
2090 DSI_LANE_DATA2,
2091 DSI_LANE_DATA3,
2092 DSI_LANE_DATA4,
2093 };
2094
2095 lanes[0] = dssdev->phy.dsi.clk_lane;
2096 lanes[1] = dssdev->phy.dsi.data1_lane;
2097 lanes[2] = dssdev->phy.dsi.data2_lane;
2098 lanes[3] = dssdev->phy.dsi.data3_lane;
2099 lanes[4] = dssdev->phy.dsi.data4_lane;
2100 polarities[0] = dssdev->phy.dsi.clk_pol;
2101 polarities[1] = dssdev->phy.dsi.data1_pol;
2102 polarities[2] = dssdev->phy.dsi.data2_pol;
2103 polarities[3] = dssdev->phy.dsi.data3_pol;
2104 polarities[4] = dssdev->phy.dsi.data4_pol;
2096 2105
2097 int clk_lane = dssdev->phy.dsi.clk_lane; 2106 num_lanes = 0;
2098 int data1_lane = dssdev->phy.dsi.data1_lane; 2107
2099 int data2_lane = dssdev->phy.dsi.data2_lane; 2108 for (i = 0; i < dsi->num_lanes_supported; ++i)
2100 int clk_pol = dssdev->phy.dsi.clk_pol; 2109 dsi->lanes[i].function = DSI_LANE_UNUSED;
2101 int data1_pol = dssdev->phy.dsi.data1_pol; 2110
2102 int data2_pol = dssdev->phy.dsi.data2_pol; 2111 for (i = 0; i < dsi->num_lanes_supported; ++i) {
2112 int num;
2113
2114 if (lanes[i] == DSI_LANE_UNUSED)
2115 break;
2116
2117 num = lanes[i] - 1;
2118
2119 if (num >= dsi->num_lanes_supported)
2120 return -EINVAL;
2121
2122 if (dsi->lanes[num].function != DSI_LANE_UNUSED)
2123 return -EINVAL;
2124
2125 dsi->lanes[num].function = functions[i];
2126 dsi->lanes[num].polarity = polarities[i];
2127 num_lanes++;
2128 }
2129
2130 if (num_lanes < 2 || num_lanes > dsi->num_lanes_supported)
2131 return -EINVAL;
2132
2133 dsi->num_lanes_used = num_lanes;
2134
2135 return 0;
2136}
2137
2138static int dsi_set_lane_config(struct omap_dss_device *dssdev)
2139{
2140 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2141 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2142 static const u8 offsets[] = { 0, 4, 8, 12, 16 };
2143 static const enum dsi_lane_function functions[] = {
2144 DSI_LANE_CLK,
2145 DSI_LANE_DATA1,
2146 DSI_LANE_DATA2,
2147 DSI_LANE_DATA3,
2148 DSI_LANE_DATA4,
2149 };
2150 u32 r;
2151 int i;
2103 2152
2104 r = dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1); 2153 r = dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1);
2105 r = FLD_MOD(r, clk_lane, 2, 0); 2154
2106 r = FLD_MOD(r, clk_pol, 3, 3); 2155 for (i = 0; i < dsi->num_lanes_used; ++i) {
2107 r = FLD_MOD(r, data1_lane, 6, 4); 2156 unsigned offset = offsets[i];
2108 r = FLD_MOD(r, data1_pol, 7, 7); 2157 unsigned polarity, lane_number;
2109 r = FLD_MOD(r, data2_lane, 10, 8); 2158 unsigned t;
2110 r = FLD_MOD(r, data2_pol, 11, 11); 2159
2111 if (num_data_lanes_dssdev > 2) { 2160 for (t = 0; t < dsi->num_lanes_supported; ++t)
2112 int data3_lane = dssdev->phy.dsi.data3_lane; 2161 if (dsi->lanes[t].function == functions[i])
2113 int data3_pol = dssdev->phy.dsi.data3_pol; 2162 break;
2114 2163
2115 r = FLD_MOD(r, data3_lane, 14, 12); 2164 if (t == dsi->num_lanes_supported)
2116 r = FLD_MOD(r, data3_pol, 15, 15); 2165 return -EINVAL;
2166
2167 lane_number = t;
2168 polarity = dsi->lanes[t].polarity;
2169
2170 r = FLD_MOD(r, lane_number + 1, offset + 2, offset);
2171 r = FLD_MOD(r, polarity, offset + 3, offset + 3);
2117 } 2172 }
2118 if (num_data_lanes_dssdev > 3) {
2119 int data4_lane = dssdev->phy.dsi.data4_lane;
2120 int data4_pol = dssdev->phy.dsi.data4_pol;
2121 2173
2122 r = FLD_MOD(r, data4_lane, 18, 16); 2174 /* clear the unused lanes */
2123 r = FLD_MOD(r, data4_pol, 19, 19); 2175 for (; i < dsi->num_lanes_supported; ++i) {
2176 unsigned offset = offsets[i];
2177
2178 r = FLD_MOD(r, 0, offset + 2, offset);
2179 r = FLD_MOD(r, 0, offset + 3, offset + 3);
2124 } 2180 }
2125 dsi_write_reg(dsidev, DSI_COMPLEXIO_CFG1, r);
2126 2181
2127 /* The configuration of the DSI complex I/O (number of data lanes, 2182 dsi_write_reg(dsidev, DSI_COMPLEXIO_CFG1, r);
2128 position, differential order) should not be changed while
2129 DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. In order for
2130 the hardware to take into account a new configuration of the complex
2131 I/O (done in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to
2132 follow this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1,
2133 then reset the DSS.DSI_CTRL[0] IF_EN to 0, then set
2134 DSS.DSI_CLK_CTRL[20] LP_CLK_ENABLE to 1 and finally set again the
2135 DSS.DSI_CTRL[0] IF_EN bit to 1. If the sequence is not followed, the
2136 DSI complex I/O configuration is unknown. */
2137 2183
2138 /* 2184 return 0;
2139 REG_FLD_MOD(dsidev, DSI_CTRL, 1, 0, 0);
2140 REG_FLD_MOD(dsidev, DSI_CTRL, 0, 0, 0);
2141 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20);
2142 REG_FLD_MOD(dsidev, DSI_CTRL, 1, 0, 0);
2143 */
2144} 2185}
2145 2186
2146static inline unsigned ns2ddr(struct platform_device *dsidev, unsigned ns) 2187static inline unsigned ns2ddr(struct platform_device *dsidev, unsigned ns)
@@ -2230,49 +2271,28 @@ static void dsi_cio_timings(struct platform_device *dsidev)
2230 dsi_write_reg(dsidev, DSI_DSIPHY_CFG2, r); 2271 dsi_write_reg(dsidev, DSI_DSIPHY_CFG2, r);
2231} 2272}
2232 2273
2274/* lane masks have lane 0 at lsb. mask_p for positive lines, n for negative */
2233static void dsi_cio_enable_lane_override(struct omap_dss_device *dssdev, 2275static void dsi_cio_enable_lane_override(struct omap_dss_device *dssdev,
2234 enum dsi_lane lanes) 2276 unsigned mask_p, unsigned mask_n)
2235{ 2277{
2236 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 2278 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2237 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2279 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2238 int clk_lane = dssdev->phy.dsi.clk_lane; 2280 int i;
2239 int data1_lane = dssdev->phy.dsi.data1_lane; 2281 u32 l;
2240 int data2_lane = dssdev->phy.dsi.data2_lane; 2282 u8 lptxscp_start = dsi->num_lanes_supported == 3 ? 22 : 26;
2241 int data3_lane = dssdev->phy.dsi.data3_lane; 2283
2242 int data4_lane = dssdev->phy.dsi.data4_lane; 2284 l = 0;
2243 int clk_pol = dssdev->phy.dsi.clk_pol; 2285
2244 int data1_pol = dssdev->phy.dsi.data1_pol; 2286 for (i = 0; i < dsi->num_lanes_supported; ++i) {
2245 int data2_pol = dssdev->phy.dsi.data2_pol; 2287 unsigned p = dsi->lanes[i].polarity;
2246 int data3_pol = dssdev->phy.dsi.data3_pol; 2288
2247 int data4_pol = dssdev->phy.dsi.data4_pol; 2289 if (mask_p & (1 << i))
2248 2290 l |= 1 << (i * 2 + (p ? 0 : 1));
2249 u32 l = 0; 2291
2250 u8 lptxscp_start = dsi->num_data_lanes == 2 ? 22 : 26; 2292 if (mask_n & (1 << i))
2251 2293 l |= 1 << (i * 2 + (p ? 1 : 0));
2252 if (lanes & DSI_CLK_P) 2294 }
2253 l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 0 : 1)); 2295
2254 if (lanes & DSI_CLK_N)
2255 l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 1 : 0));
2256
2257 if (lanes & DSI_DATA1_P)
2258 l |= 1 << ((data1_lane - 1) * 2 + (data1_pol ? 0 : 1));
2259 if (lanes & DSI_DATA1_N)
2260 l |= 1 << ((data1_lane - 1) * 2 + (data1_pol ? 1 : 0));
2261
2262 if (lanes & DSI_DATA2_P)
2263 l |= 1 << ((data2_lane - 1) * 2 + (data2_pol ? 0 : 1));
2264 if (lanes & DSI_DATA2_N)
2265 l |= 1 << ((data2_lane - 1) * 2 + (data2_pol ? 1 : 0));
2266
2267 if (lanes & DSI_DATA3_P)
2268 l |= 1 << ((data3_lane - 1) * 2 + (data3_pol ? 0 : 1));
2269 if (lanes & DSI_DATA3_N)
2270 l |= 1 << ((data3_lane - 1) * 2 + (data3_pol ? 1 : 0));
2271
2272 if (lanes & DSI_DATA4_P)
2273 l |= 1 << ((data4_lane - 1) * 2 + (data4_pol ? 0 : 1));
2274 if (lanes & DSI_DATA4_N)
2275 l |= 1 << ((data4_lane - 1) * 2 + (data4_pol ? 1 : 0));
2276 /* 2296 /*
2277 * Bits in REGLPTXSCPDAT4TO0DXDY: 2297 * Bits in REGLPTXSCPDAT4TO0DXDY:
2278 * 17: DY0 18: DX0 2298 * 17: DY0 18: DX0
@@ -2305,51 +2325,40 @@ static void dsi_cio_disable_lane_override(struct platform_device *dsidev)
2305static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev) 2325static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev)
2306{ 2326{
2307 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 2327 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2308 int t; 2328 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2309 int bits[3]; 2329 int t, i;
2310 bool in_use[3]; 2330 bool in_use[DSI_MAX_NR_LANES];
2311 2331 static const u8 offsets_old[] = { 28, 27, 26 };
2312 if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) { 2332 static const u8 offsets_new[] = { 24, 25, 26, 27, 28 };
2313 bits[0] = 28; 2333 const u8 *offsets;
2314 bits[1] = 27; 2334
2315 bits[2] = 26; 2335 if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC))
2316 } else { 2336 offsets = offsets_old;
2317 bits[0] = 24; 2337 else
2318 bits[1] = 25; 2338 offsets = offsets_new;
2319 bits[2] = 26;
2320 }
2321
2322 in_use[0] = false;
2323 in_use[1] = false;
2324 in_use[2] = false;
2325 2339
2326 if (dssdev->phy.dsi.clk_lane != 0) 2340 for (i = 0; i < dsi->num_lanes_supported; ++i)
2327 in_use[dssdev->phy.dsi.clk_lane - 1] = true; 2341 in_use[i] = dsi->lanes[i].function != DSI_LANE_UNUSED;
2328 if (dssdev->phy.dsi.data1_lane != 0)
2329 in_use[dssdev->phy.dsi.data1_lane - 1] = true;
2330 if (dssdev->phy.dsi.data2_lane != 0)
2331 in_use[dssdev->phy.dsi.data2_lane - 1] = true;
2332 2342
2333 t = 100000; 2343 t = 100000;
2334 while (true) { 2344 while (true) {
2335 u32 l; 2345 u32 l;
2336 int i;
2337 int ok; 2346 int ok;
2338 2347
2339 l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5); 2348 l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
2340 2349
2341 ok = 0; 2350 ok = 0;
2342 for (i = 0; i < 3; ++i) { 2351 for (i = 0; i < dsi->num_lanes_supported; ++i) {
2343 if (!in_use[i] || (l & (1 << bits[i]))) 2352 if (!in_use[i] || (l & (1 << offsets[i])))
2344 ok++; 2353 ok++;
2345 } 2354 }
2346 2355
2347 if (ok == 3) 2356 if (ok == dsi->num_lanes_supported)
2348 break; 2357 break;
2349 2358
2350 if (--t == 0) { 2359 if (--t == 0) {
2351 for (i = 0; i < 3; ++i) { 2360 for (i = 0; i < dsi->num_lanes_supported; ++i) {
2352 if (!in_use[i] || (l & (1 << bits[i]))) 2361 if (!in_use[i] || (l & (1 << offsets[i])))
2353 continue; 2362 continue;
2354 2363
2355 DSSERR("CIO TXCLKESC%d domain not coming " \ 2364 DSSERR("CIO TXCLKESC%d domain not coming " \
@@ -2362,22 +2371,20 @@ static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev)
2362 return 0; 2371 return 0;
2363} 2372}
2364 2373
2374/* return bitmask of enabled lanes, lane0 being the lsb */
2365static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev) 2375static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev)
2366{ 2376{
2367 unsigned lanes = 0; 2377 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2378 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2379 unsigned mask = 0;
2380 int i;
2368 2381
2369 if (dssdev->phy.dsi.clk_lane != 0) 2382 for (i = 0; i < dsi->num_lanes_supported; ++i) {
2370 lanes |= 1 << (dssdev->phy.dsi.clk_lane - 1); 2383 if (dsi->lanes[i].function != DSI_LANE_UNUSED)
2371 if (dssdev->phy.dsi.data1_lane != 0) 2384 mask |= 1 << i;
2372 lanes |= 1 << (dssdev->phy.dsi.data1_lane - 1); 2385 }
2373 if (dssdev->phy.dsi.data2_lane != 0)
2374 lanes |= 1 << (dssdev->phy.dsi.data2_lane - 1);
2375 if (dssdev->phy.dsi.data3_lane != 0)
2376 lanes |= 1 << (dssdev->phy.dsi.data3_lane - 1);
2377 if (dssdev->phy.dsi.data4_lane != 0)
2378 lanes |= 1 << (dssdev->phy.dsi.data4_lane - 1);
2379 2386
2380 return lanes; 2387 return mask;
2381} 2388}
2382 2389
2383static int dsi_cio_init(struct omap_dss_device *dssdev) 2390static int dsi_cio_init(struct omap_dss_device *dssdev)
@@ -2385,7 +2392,6 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
2385 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 2392 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
2386 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2393 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
2387 int r; 2394 int r;
2388 int num_data_lanes_dssdev = dsi_get_num_data_lanes_dssdev(dssdev);
2389 u32 l; 2395 u32 l;
2390 2396
2391 DSSDBGF(); 2397 DSSDBGF();
@@ -2407,7 +2413,9 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
2407 goto err_scp_clk_dom; 2413 goto err_scp_clk_dom;
2408 } 2414 }
2409 2415
2410 dsi_set_lane_config(dssdev); 2416 r = dsi_set_lane_config(dssdev);
2417 if (r)
2418 goto err_scp_clk_dom;
2411 2419
2412 /* set TX STOP MODE timer to maximum for this operation */ 2420 /* set TX STOP MODE timer to maximum for this operation */
2413 l = dsi_read_reg(dsidev, DSI_TIMING1); 2421 l = dsi_read_reg(dsidev, DSI_TIMING1);
@@ -2418,7 +2426,8 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
2418 dsi_write_reg(dsidev, DSI_TIMING1, l); 2426 dsi_write_reg(dsidev, DSI_TIMING1, l);
2419 2427
2420 if (dsi->ulps_enabled) { 2428 if (dsi->ulps_enabled) {
2421 u32 lane_mask = DSI_CLK_P | DSI_DATA1_P | DSI_DATA2_P; 2429 unsigned mask_p;
2430 int i;
2422 2431
2423 DSSDBG("manual ulps exit\n"); 2432 DSSDBG("manual ulps exit\n");
2424 2433
@@ -2427,16 +2436,19 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
2427 * ULPS exit sequence, as after reset the DSS HW thinks 2436 * ULPS exit sequence, as after reset the DSS HW thinks
2428 * that we are not in ULPS mode, and refuses to send the 2437 * that we are not in ULPS mode, and refuses to send the
2429 * sequence. So we need to send the ULPS exit sequence 2438 * sequence. So we need to send the ULPS exit sequence
2430 * manually. 2439 * manually by setting positive lines high and negative lines
2440 * low for 1ms.
2431 */ 2441 */
2432 2442
2433 if (num_data_lanes_dssdev > 2) 2443 mask_p = 0;
2434 lane_mask |= DSI_DATA3_P;
2435 2444
2436 if (num_data_lanes_dssdev > 3) 2445 for (i = 0; i < dsi->num_lanes_supported; ++i) {
2437 lane_mask |= DSI_DATA4_P; 2446 if (dsi->lanes[i].function == DSI_LANE_UNUSED)
2447 continue;
2448 mask_p |= 1 << i;
2449 }
2438 2450
2439 dsi_cio_enable_lane_override(dssdev, lane_mask); 2451 dsi_cio_enable_lane_override(dssdev, mask_p, 0);
2440 } 2452 }
2441 2453
2442 r = dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ON); 2454 r = dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ON);
@@ -2913,6 +2925,9 @@ static int dsi_vc_send_bta(struct platform_device *dsidev, int channel)
2913 2925
2914 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */ 2926 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */
2915 2927
2928 /* flush posted write */
2929 dsi_read_reg(dsidev, DSI_VC_CTRL(channel));
2930
2916 return 0; 2931 return 0;
2917} 2932}
2918 2933
@@ -3513,7 +3528,8 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
3513{ 3528{
3514 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 3529 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3515 DECLARE_COMPLETION_ONSTACK(completion); 3530 DECLARE_COMPLETION_ONSTACK(completion);
3516 int r; 3531 int r, i;
3532 unsigned mask;
3517 3533
3518 DSSDBGF(); 3534 DSSDBGF();
3519 3535
@@ -3524,9 +3540,11 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
3524 if (dsi->ulps_enabled) 3540 if (dsi->ulps_enabled)
3525 return 0; 3541 return 0;
3526 3542
3543 /* DDR_CLK_ALWAYS_ON */
3527 if (REG_GET(dsidev, DSI_CLK_CTRL, 13, 13)) { 3544 if (REG_GET(dsidev, DSI_CLK_CTRL, 13, 13)) {
3528 DSSERR("DDR_CLK_ALWAYS_ON enabled when entering ULPS\n"); 3545 dsi_if_enable(dsidev, 0);
3529 return -EIO; 3546 REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 13, 13);
3547 dsi_if_enable(dsidev, 1);
3530 } 3548 }
3531 3549
3532 dsi_sync_vc(dsidev, 0); 3550 dsi_sync_vc(dsidev, 0);
@@ -3556,10 +3574,19 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
3556 if (r) 3574 if (r)
3557 return r; 3575 return r;
3558 3576
3577 mask = 0;
3578
3579 for (i = 0; i < dsi->num_lanes_supported; ++i) {
3580 if (dsi->lanes[i].function == DSI_LANE_UNUSED)
3581 continue;
3582 mask |= 1 << i;
3583 }
3559 /* Assert TxRequestEsc for data lanes and TxUlpsClk for clk lane */ 3584 /* Assert TxRequestEsc for data lanes and TxUlpsClk for clk lane */
3560 /* LANEx_ULPS_SIG2 */ 3585 /* LANEx_ULPS_SIG2 */
3561 REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (1 << 0) | (1 << 1) | (1 << 2), 3586 REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, mask, 9, 5);
3562 7, 5); 3587
3588 /* flush posted write and wait for SCP interface to finish the write */
3589 dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG2);
3563 3590
3564 if (wait_for_completion_timeout(&completion, 3591 if (wait_for_completion_timeout(&completion,
3565 msecs_to_jiffies(1000)) == 0) { 3592 msecs_to_jiffies(1000)) == 0) {
@@ -3572,8 +3599,10 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
3572 DSI_CIO_IRQ_ULPSACTIVENOT_ALL0); 3599 DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
3573 3600
3574 /* Reset LANEx_ULPS_SIG2 */ 3601 /* Reset LANEx_ULPS_SIG2 */
3575 REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (0 << 0) | (0 << 1) | (0 << 2), 3602 REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, 0, 9, 5);
3576 7, 5); 3603
3604 /* flush posted write and wait for SCP interface to finish the write */
3605 dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG2);
3577 3606
3578 dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ULPS); 3607 dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ULPS);
3579 3608
@@ -3836,6 +3865,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
3836static void dsi_proto_timings(struct omap_dss_device *dssdev) 3865static void dsi_proto_timings(struct omap_dss_device *dssdev)
3837{ 3866{
3838 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3867 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3868 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
3839 unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail; 3869 unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail;
3840 unsigned tclk_pre, tclk_post; 3870 unsigned tclk_pre, tclk_post;
3841 unsigned ths_prepare, ths_prepare_ths_zero, ths_zero; 3871 unsigned ths_prepare, ths_prepare_ths_zero, ths_zero;
@@ -3843,7 +3873,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
3843 unsigned ddr_clk_pre, ddr_clk_post; 3873 unsigned ddr_clk_pre, ddr_clk_post;
3844 unsigned enter_hs_mode_lat, exit_hs_mode_lat; 3874 unsigned enter_hs_mode_lat, exit_hs_mode_lat;
3845 unsigned ths_eot; 3875 unsigned ths_eot;
3846 int ndl = dsi_get_num_data_lanes_dssdev(dssdev); 3876 int ndl = dsi->num_lanes_used - 1;
3847 u32 r; 3877 u32 r;
3848 3878
3849 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0); 3879 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0);
@@ -3945,68 +3975,82 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
3945 } 3975 }
3946} 3976}
3947 3977
3948int dsi_video_mode_enable(struct omap_dss_device *dssdev, int channel) 3978int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
3949{ 3979{
3950 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3980 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3951 int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); 3981 int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
3952 u8 data_type; 3982 u8 data_type;
3953 u16 word_count; 3983 u16 word_count;
3984 int r;
3954 3985
3955 switch (dssdev->panel.dsi_pix_fmt) { 3986 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
3956 case OMAP_DSS_DSI_FMT_RGB888: 3987 switch (dssdev->panel.dsi_pix_fmt) {
3957 data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24; 3988 case OMAP_DSS_DSI_FMT_RGB888:
3958 break; 3989 data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24;
3959 case OMAP_DSS_DSI_FMT_RGB666: 3990 break;
3960 data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18; 3991 case OMAP_DSS_DSI_FMT_RGB666:
3961 break; 3992 data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
3962 case OMAP_DSS_DSI_FMT_RGB666_PACKED: 3993 break;
3963 data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18; 3994 case OMAP_DSS_DSI_FMT_RGB666_PACKED:
3964 break; 3995 data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18;
3965 case OMAP_DSS_DSI_FMT_RGB565: 3996 break;
3966 data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16; 3997 case OMAP_DSS_DSI_FMT_RGB565:
3967 break; 3998 data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16;
3968 default: 3999 break;
3969 BUG(); 4000 default:
3970 }; 4001 BUG();
4002 };
3971 4003
3972 dsi_if_enable(dsidev, false); 4004 dsi_if_enable(dsidev, false);
3973 dsi_vc_enable(dsidev, channel, false); 4005 dsi_vc_enable(dsidev, channel, false);
3974 4006
3975 /* MODE, 1 = video mode */ 4007 /* MODE, 1 = video mode */
3976 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4); 4008 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4);
3977 4009
3978 word_count = DIV_ROUND_UP(dssdev->panel.timings.x_res * bpp, 8); 4010 word_count = DIV_ROUND_UP(dssdev->panel.timings.x_res * bpp, 8);
3979 4011
3980 dsi_vc_write_long_header(dsidev, channel, data_type, word_count, 0); 4012 dsi_vc_write_long_header(dsidev, channel, data_type,
4013 word_count, 0);
3981 4014
3982 dsi_vc_enable(dsidev, channel, true); 4015 dsi_vc_enable(dsidev, channel, true);
3983 dsi_if_enable(dsidev, true); 4016 dsi_if_enable(dsidev, true);
4017 }
3984 4018
3985 dssdev->manager->enable(dssdev->manager); 4019 r = dss_mgr_enable(dssdev->manager);
4020 if (r) {
4021 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
4022 dsi_if_enable(dsidev, false);
4023 dsi_vc_enable(dsidev, channel, false);
4024 }
4025
4026 return r;
4027 }
3986 4028
3987 return 0; 4029 return 0;
3988} 4030}
3989EXPORT_SYMBOL(dsi_video_mode_enable); 4031EXPORT_SYMBOL(dsi_enable_video_output);
3990 4032
3991void dsi_video_mode_disable(struct omap_dss_device *dssdev, int channel) 4033void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)
3992{ 4034{
3993 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4035 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
3994 4036
3995 dsi_if_enable(dsidev, false); 4037 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
3996 dsi_vc_enable(dsidev, channel, false); 4038 dsi_if_enable(dsidev, false);
4039 dsi_vc_enable(dsidev, channel, false);
3997 4040
3998 /* MODE, 0 = command mode */ 4041 /* MODE, 0 = command mode */
3999 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 4, 4); 4042 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 4, 4);
4000 4043
4001 dsi_vc_enable(dsidev, channel, true); 4044 dsi_vc_enable(dsidev, channel, true);
4002 dsi_if_enable(dsidev, true); 4045 dsi_if_enable(dsidev, true);
4046 }
4003 4047
4004 dssdev->manager->disable(dssdev->manager); 4048 dss_mgr_disable(dssdev->manager);
4005} 4049}
4006EXPORT_SYMBOL(dsi_video_mode_disable); 4050EXPORT_SYMBOL(dsi_disable_video_output);
4007 4051
4008static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, 4052static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
4009 u16 x, u16 y, u16 w, u16 h) 4053 u16 w, u16 h)
4010{ 4054{
4011 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4055 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4012 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4056 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
@@ -4021,8 +4065,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
4021 const unsigned channel = dsi->update_channel; 4065 const unsigned channel = dsi->update_channel;
4022 const unsigned line_buf_size = dsi_get_line_buf_size(dsidev); 4066 const unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
4023 4067
4024 DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n", 4068 DSSDBG("dsi_update_screen_dispc(%dx%d)\n", w, h);
4025 x, y, w, h);
4026 4069
4027 dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP); 4070 dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP);
4028 4071
@@ -4070,7 +4113,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
4070 msecs_to_jiffies(250)); 4113 msecs_to_jiffies(250));
4071 BUG_ON(r == 0); 4114 BUG_ON(r == 0);
4072 4115
4073 dss_start_update(dssdev); 4116 dss_mgr_start_update(dssdev->manager);
4074 4117
4075 if (dsi->te_enabled) { 4118 if (dsi->te_enabled) {
4076 /* disable LP_RX_TO, so that we can receive TE. Time to wait 4119 /* disable LP_RX_TO, so that we can receive TE. Time to wait
@@ -4146,66 +4189,27 @@ static void dsi_framedone_irq_callback(void *data, u32 mask)
4146#endif 4189#endif
4147} 4190}
4148 4191
4149int omap_dsi_prepare_update(struct omap_dss_device *dssdev, 4192int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
4150 u16 *x, u16 *y, u16 *w, u16 *h, 4193 void (*callback)(int, void *), void *data)
4151 bool enlarge_update_area)
4152{ 4194{
4153 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4195 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4196 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4154 u16 dw, dh; 4197 u16 dw, dh;
4155 4198
4156 dssdev->driver->get_resolution(dssdev, &dw, &dh);
4157
4158 if (*x > dw || *y > dh)
4159 return -EINVAL;
4160
4161 if (*x + *w > dw)
4162 return -EINVAL;
4163
4164 if (*y + *h > dh)
4165 return -EINVAL;
4166
4167 if (*w == 1)
4168 return -EINVAL;
4169
4170 if (*w == 0 || *h == 0)
4171 return -EINVAL;
4172
4173 dsi_perf_mark_setup(dsidev); 4199 dsi_perf_mark_setup(dsidev);
4174 4200
4175 dss_setup_partial_planes(dssdev, x, y, w, h,
4176 enlarge_update_area);
4177 dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h);
4178
4179 return 0;
4180}
4181EXPORT_SYMBOL(omap_dsi_prepare_update);
4182
4183int omap_dsi_update(struct omap_dss_device *dssdev,
4184 int channel,
4185 u16 x, u16 y, u16 w, u16 h,
4186 void (*callback)(int, void *), void *data)
4187{
4188 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4189 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4190
4191 dsi->update_channel = channel; 4201 dsi->update_channel = channel;
4192 4202
4193 /* OMAP DSS cannot send updates of odd widths.
4194 * omap_dsi_prepare_update() makes the widths even, but add a BUG_ON
4195 * here to make sure we catch erroneous updates. Otherwise we'll only
4196 * see rather obscure HW error happening, as DSS halts. */
4197 BUG_ON(x % 2 == 1);
4198
4199 dsi->framedone_callback = callback; 4203 dsi->framedone_callback = callback;
4200 dsi->framedone_data = data; 4204 dsi->framedone_data = data;
4201 4205
4202 dsi->update_region.x = x; 4206 dssdev->driver->get_resolution(dssdev, &dw, &dh);
4203 dsi->update_region.y = y;
4204 dsi->update_region.w = w;
4205 dsi->update_region.h = h;
4206 dsi->update_region.device = dssdev;
4207 4207
4208 dsi_update_screen_dispc(dssdev, x, y, w, h); 4208#ifdef DEBUG
4209 dsi->update_bytes = dw * dh *
4210 dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8;
4211#endif
4212 dsi_update_screen_dispc(dssdev, dw, dh);
4209 4213
4210 return 0; 4214 return 0;
4211} 4215}
@@ -4218,6 +4222,7 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4218 int r; 4222 int r;
4219 4223
4220 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { 4224 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) {
4225 u16 dw, dh;
4221 u32 irq; 4226 u32 irq;
4222 struct omap_video_timings timings = { 4227 struct omap_video_timings timings = {
4223 .hsw = 1, 4228 .hsw = 1,
@@ -4228,6 +4233,10 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
4228 .vbp = 0, 4233 .vbp = 0,
4229 }; 4234 };
4230 4235
4236 dssdev->driver->get_resolution(dssdev, &dw, &dh);
4237 timings.x_res = dw;
4238 timings.y_res = dh;
4239
4231 irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? 4240 irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ?
4232 DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; 4241 DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2;
4233 4242
@@ -4330,6 +4339,12 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
4330 int dsi_module = dsi_get_dsidev_id(dsidev); 4339 int dsi_module = dsi_get_dsidev_id(dsidev);
4331 int r; 4340 int r;
4332 4341
4342 r = dsi_parse_lane_config(dssdev);
4343 if (r) {
4344 DSSERR("illegal lane config");
4345 goto err0;
4346 }
4347
4333 r = dsi_pll_init(dsidev, true, true); 4348 r = dsi_pll_init(dsidev, true, true);
4334 if (r) 4349 if (r)
4335 goto err0; 4350 goto err0;
@@ -4521,7 +4536,6 @@ int dsi_init_display(struct omap_dss_device *dssdev)
4521{ 4536{
4522 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4537 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
4523 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4538 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
4524 int dsi_module = dsi_get_dsidev_id(dsidev);
4525 4539
4526 DSSDBG("DSI init\n"); 4540 DSSDBG("DSI init\n");
4527 4541
@@ -4543,12 +4557,6 @@ int dsi_init_display(struct omap_dss_device *dssdev)
4543 dsi->vdds_dsi_reg = vdds_dsi; 4557 dsi->vdds_dsi_reg = vdds_dsi;
4544 } 4558 }
4545 4559
4546 if (dsi_get_num_data_lanes_dssdev(dssdev) > dsi->num_data_lanes) {
4547 DSSERR("DSI%d can't support more than %d data lanes\n",
4548 dsi_module + 1, dsi->num_data_lanes);
4549 return -EINVAL;
4550 }
4551
4552 return 0; 4560 return 0;
4553} 4561}
4554 4562
@@ -4771,7 +4779,13 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
4771 dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n", 4779 dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n",
4772 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); 4780 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
4773 4781
4774 dsi->num_data_lanes = dsi_get_num_data_lanes(dsidev); 4782 /* DSI on OMAP3 doesn't have register DSI_GNQ, set number
4783 * of data to 3 by default */
4784 if (dss_has_feature(FEAT_DSI_GNQ))
4785 /* NB_DATA_LANES */
4786 dsi->num_lanes_supported = 1 + REG_GET(dsidev, DSI_GNQ, 11, 9);
4787 else
4788 dsi->num_lanes_supported = 3;
4775 4789
4776 dsi_runtime_put(dsidev); 4790 dsi_runtime_put(dsidev);
4777 4791
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 57a52eecee91..32ff69fb3333 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -163,6 +163,34 @@ struct bus_type *dss_get_bus(void);
163struct regulator *dss_get_vdds_dsi(void); 163struct regulator *dss_get_vdds_dsi(void);
164struct regulator *dss_get_vdds_sdi(void); 164struct regulator *dss_get_vdds_sdi(void);
165 165
166/* apply */
167void dss_apply_init(void);
168int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr);
169int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
170void dss_mgr_start_update(struct omap_overlay_manager *mgr);
171int omap_dss_mgr_apply(struct omap_overlay_manager *mgr);
172
173int dss_mgr_enable(struct omap_overlay_manager *mgr);
174void dss_mgr_disable(struct omap_overlay_manager *mgr);
175int dss_mgr_set_info(struct omap_overlay_manager *mgr,
176 struct omap_overlay_manager_info *info);
177void dss_mgr_get_info(struct omap_overlay_manager *mgr,
178 struct omap_overlay_manager_info *info);
179int dss_mgr_set_device(struct omap_overlay_manager *mgr,
180 struct omap_dss_device *dssdev);
181int dss_mgr_unset_device(struct omap_overlay_manager *mgr);
182
183bool dss_ovl_is_enabled(struct omap_overlay *ovl);
184int dss_ovl_enable(struct omap_overlay *ovl);
185int dss_ovl_disable(struct omap_overlay *ovl);
186int dss_ovl_set_info(struct omap_overlay *ovl,
187 struct omap_overlay_info *info);
188void dss_ovl_get_info(struct omap_overlay *ovl,
189 struct omap_overlay_info *info);
190int dss_ovl_set_manager(struct omap_overlay *ovl,
191 struct omap_overlay_manager *mgr);
192int dss_ovl_unset_manager(struct omap_overlay *ovl);
193
166/* display */ 194/* display */
167int dss_suspend_all_devices(void); 195int dss_suspend_all_devices(void);
168int dss_resume_all_devices(void); 196int dss_resume_all_devices(void);
@@ -181,21 +209,22 @@ void default_get_overlay_fifo_thresholds(enum omap_plane plane,
181/* manager */ 209/* manager */
182int dss_init_overlay_managers(struct platform_device *pdev); 210int dss_init_overlay_managers(struct platform_device *pdev);
183void dss_uninit_overlay_managers(struct platform_device *pdev); 211void dss_uninit_overlay_managers(struct platform_device *pdev);
184int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl); 212int dss_mgr_simple_check(struct omap_overlay_manager *mgr,
185void dss_setup_partial_planes(struct omap_dss_device *dssdev, 213 const struct omap_overlay_manager_info *info);
186 u16 *x, u16 *y, u16 *w, u16 *h, 214int dss_mgr_check(struct omap_overlay_manager *mgr,
187 bool enlarge_update_area); 215 struct omap_dss_device *dssdev,
188void dss_start_update(struct omap_dss_device *dssdev); 216 struct omap_overlay_manager_info *info,
217 struct omap_overlay_info **overlay_infos);
189 218
190/* overlay */ 219/* overlay */
191void dss_init_overlays(struct platform_device *pdev); 220void dss_init_overlays(struct platform_device *pdev);
192void dss_uninit_overlays(struct platform_device *pdev); 221void dss_uninit_overlays(struct platform_device *pdev);
193int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev);
194void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr); 222void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr);
195#ifdef L4_EXAMPLE
196void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr);
197#endif
198void dss_recheck_connections(struct omap_dss_device *dssdev, bool force); 223void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
224int dss_ovl_simple_check(struct omap_overlay *ovl,
225 const struct omap_overlay_info *info);
226int dss_ovl_check(struct omap_overlay *ovl,
227 struct omap_overlay_info *info, struct omap_dss_device *dssdev);
199 228
200/* DSS */ 229/* DSS */
201int dss_init_platform_driver(void); 230int dss_init_platform_driver(void);
@@ -399,21 +428,22 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
399 struct dispc_clock_info *cinfo); 428 struct dispc_clock_info *cinfo);
400 429
401 430
431void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
402u32 dispc_ovl_get_fifo_size(enum omap_plane plane); 432u32 dispc_ovl_get_fifo_size(enum omap_plane plane);
403u32 dispc_ovl_get_burst_size(enum omap_plane plane); 433u32 dispc_ovl_get_burst_size(enum omap_plane plane);
404int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, 434int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
405 bool ilace, enum omap_channel channel, bool replication, 435 bool ilace, bool replication);
406 u32 fifo_low, u32 fifo_high);
407int dispc_ovl_enable(enum omap_plane plane, bool enable); 436int dispc_ovl_enable(enum omap_plane plane, bool enable);
408 437void dispc_ovl_set_channel_out(enum omap_plane plane,
438 enum omap_channel channel);
409 439
410void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable); 440void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable);
411void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height); 441void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height);
412void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable); 442u32 dispc_mgr_get_vsync_irq(enum omap_channel channel);
413void dispc_mgr_set_cpr_coef(enum omap_channel channel, 443u32 dispc_mgr_get_framedone_irq(enum omap_channel channel);
414 struct omap_dss_cpr_coefs *coefs);
415bool dispc_mgr_go_busy(enum omap_channel channel); 444bool dispc_mgr_go_busy(enum omap_channel channel);
416void dispc_mgr_go(enum omap_channel channel); 445void dispc_mgr_go(enum omap_channel channel);
446bool dispc_mgr_is_enabled(enum omap_channel channel);
417void dispc_mgr_enable(enum omap_channel channel, bool enable); 447void dispc_mgr_enable(enum omap_channel channel, bool enable);
418bool dispc_mgr_is_channel_enabled(enum omap_channel channel); 448bool dispc_mgr_is_channel_enabled(enum omap_channel channel);
419void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode); 449void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode);
@@ -421,18 +451,6 @@ void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable);
421void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines); 451void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines);
422void dispc_mgr_set_lcd_display_type(enum omap_channel channel, 452void dispc_mgr_set_lcd_display_type(enum omap_channel channel,
423 enum omap_lcd_display_type type); 453 enum omap_lcd_display_type type);
424void dispc_mgr_set_default_color(enum omap_channel channel, u32 color);
425u32 dispc_mgr_get_default_color(enum omap_channel channel);
426void dispc_mgr_set_trans_key(enum omap_channel ch,
427 enum omap_dss_trans_key_type type,
428 u32 trans_key);
429void dispc_mgr_get_trans_key(enum omap_channel ch,
430 enum omap_dss_trans_key_type *type,
431 u32 *trans_key);
432void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable);
433void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable);
434bool dispc_mgr_trans_key_enabled(enum omap_channel ch);
435bool dispc_mgr_alpha_fixed_zorder_enabled(enum omap_channel ch);
436void dispc_mgr_set_lcd_timings(enum omap_channel channel, 454void dispc_mgr_set_lcd_timings(enum omap_channel channel,
437 struct omap_video_timings *timings); 455 struct omap_video_timings *timings);
438void dispc_mgr_set_pol_freq(enum omap_channel channel, 456void dispc_mgr_set_pol_freq(enum omap_channel channel,
@@ -443,6 +461,8 @@ int dispc_mgr_set_clock_div(enum omap_channel channel,
443 struct dispc_clock_info *cinfo); 461 struct dispc_clock_info *cinfo);
444int dispc_mgr_get_clock_div(enum omap_channel channel, 462int dispc_mgr_get_clock_div(enum omap_channel channel,
445 struct dispc_clock_info *cinfo); 463 struct dispc_clock_info *cinfo);
464void dispc_mgr_setup(enum omap_channel channel,
465 struct omap_overlay_manager_info *info);
446 466
447/* VENC */ 467/* VENC */
448#ifdef CONFIG_OMAP2_DSS_VENC 468#ifdef CONFIG_OMAP2_DSS_VENC
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index b402699168a5..afcb59301c37 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -304,6 +304,11 @@ static const struct dss_param_range omap2_dss_param_range[] = {
304 [FEAT_PARAM_DSIPLL_FINT] = { 0, 0 }, 304 [FEAT_PARAM_DSIPLL_FINT] = { 0, 0 },
305 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, 0 }, 305 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, 0 },
306 [FEAT_PARAM_DOWNSCALE] = { 1, 2 }, 306 [FEAT_PARAM_DOWNSCALE] = { 1, 2 },
307 /*
308 * Assuming the line width buffer to be 768 pixels as OMAP2 DISPC
309 * scaler cannot scale a image with width more than 768.
310 */
311 [FEAT_PARAM_LINEWIDTH] = { 1, 768 },
307}; 312};
308 313
309static const struct dss_param_range omap3_dss_param_range[] = { 314static const struct dss_param_range omap3_dss_param_range[] = {
@@ -316,6 +321,7 @@ static const struct dss_param_range omap3_dss_param_range[] = {
316 [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 }, 321 [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 },
317 [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1}, 322 [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1},
318 [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, 323 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
324 [FEAT_PARAM_LINEWIDTH] = { 1, 1024 },
319}; 325};
320 326
321static const struct dss_param_range omap4_dss_param_range[] = { 327static const struct dss_param_range omap4_dss_param_range[] = {
@@ -328,6 +334,7 @@ static const struct dss_param_range omap4_dss_param_range[] = {
328 [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 }, 334 [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 },
329 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, 335 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
330 [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, 336 [FEAT_PARAM_DOWNSCALE] = { 1, 4 },
337 [FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
331}; 338};
332 339
333/* OMAP2 DSS Features */ 340/* OMAP2 DSS Features */
@@ -465,6 +472,10 @@ static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
465 .dump_core = ti_hdmi_4xxx_core_dump, 472 .dump_core = ti_hdmi_4xxx_core_dump,
466 .dump_pll = ti_hdmi_4xxx_pll_dump, 473 .dump_pll = ti_hdmi_4xxx_pll_dump,
467 .dump_phy = ti_hdmi_4xxx_phy_dump, 474 .dump_phy = ti_hdmi_4xxx_phy_dump,
475#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
476 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
477 .audio_enable = ti_hdmi_4xxx_wp_audio_enable,
478#endif
468 479
469}; 480};
470 481
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index 6a6c05dd45ce..cd833bbaac3d 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -86,6 +86,7 @@ enum dss_range_param {
86 FEAT_PARAM_DSIPLL_FINT, 86 FEAT_PARAM_DSIPLL_FINT,
87 FEAT_PARAM_DSIPLL_LPDIV, 87 FEAT_PARAM_DSIPLL_LPDIV,
88 FEAT_PARAM_DOWNSCALE, 88 FEAT_PARAM_DOWNSCALE,
89 FEAT_PARAM_LINEWIDTH,
89}; 90};
90 91
91/* DSS Feature Functions */ 92/* DSS Feature Functions */
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index c56378c555b0..b4c270edb915 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -333,7 +333,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
333 if (r) 333 if (r)
334 return r; 334 return r;
335 335
336 dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 0); 336 dss_mgr_disable(dssdev->manager);
337 337
338 p = &dssdev->panel.timings; 338 p = &dssdev->panel.timings;
339 339
@@ -387,9 +387,16 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
387 387
388 hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 1); 388 hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 1);
389 389
390 dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 1); 390 r = dss_mgr_enable(dssdev->manager);
391 if (r)
392 goto err_mgr_enable;
391 393
392 return 0; 394 return 0;
395
396err_mgr_enable:
397 hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0);
398 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
399 hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
393err: 400err:
394 hdmi_runtime_put(); 401 hdmi_runtime_put();
395 return -EIO; 402 return -EIO;
@@ -397,7 +404,7 @@ err:
397 404
398static void hdmi_power_off(struct omap_dss_device *dssdev) 405static void hdmi_power_off(struct omap_dss_device *dssdev)
399{ 406{
400 dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 0); 407 dss_mgr_disable(dssdev->manager);
401 408
402 hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0); 409 hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0);
403 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); 410 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
@@ -554,11 +561,44 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
554#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ 561#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
555 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) 562 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
556 563
557static int hdmi_audio_hw_params(struct hdmi_ip_data *ip_data, 564static int hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
558 struct snd_pcm_substream *substream, 565 struct snd_soc_dai *dai)
566{
567 struct snd_soc_pcm_runtime *rtd = substream->private_data;
568 struct snd_soc_codec *codec = rtd->codec;
569 struct platform_device *pdev = to_platform_device(codec->dev);
570 struct hdmi_ip_data *ip_data = snd_soc_codec_get_drvdata(codec);
571 int err = 0;
572
573 if (!(ip_data->ops) && !(ip_data->ops->audio_enable)) {
574 dev_err(&pdev->dev, "Cannot enable/disable audio\n");
575 return -ENODEV;
576 }
577
578 switch (cmd) {
579 case SNDRV_PCM_TRIGGER_START:
580 case SNDRV_PCM_TRIGGER_RESUME:
581 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
582 ip_data->ops->audio_enable(ip_data, true);
583 break;
584 case SNDRV_PCM_TRIGGER_STOP:
585 case SNDRV_PCM_TRIGGER_SUSPEND:
586 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
587 ip_data->ops->audio_enable(ip_data, false);
588 break;
589 default:
590 err = -EINVAL;
591 }
592 return err;
593}
594
595static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
559 struct snd_pcm_hw_params *params, 596 struct snd_pcm_hw_params *params,
560 struct snd_soc_dai *dai) 597 struct snd_soc_dai *dai)
561{ 598{
599 struct snd_soc_pcm_runtime *rtd = substream->private_data;
600 struct snd_soc_codec *codec = rtd->codec;
601 struct hdmi_ip_data *ip_data = snd_soc_codec_get_drvdata(codec);
562 struct hdmi_audio_format audio_format; 602 struct hdmi_audio_format audio_format;
563 struct hdmi_audio_dma audio_dma; 603 struct hdmi_audio_dma audio_dma;
564 struct hdmi_core_audio_config core_cfg; 604 struct hdmi_core_audio_config core_cfg;
@@ -698,7 +738,16 @@ static int hdmi_audio_startup(struct snd_pcm_substream *substream,
698 return 0; 738 return 0;
699} 739}
700 740
741static int hdmi_audio_codec_probe(struct snd_soc_codec *codec)
742{
743 struct hdmi_ip_data *priv = &hdmi.ip_data;
744
745 snd_soc_codec_set_drvdata(codec, priv);
746 return 0;
747}
748
701static struct snd_soc_codec_driver hdmi_audio_codec_drv = { 749static struct snd_soc_codec_driver hdmi_audio_codec_drv = {
750 .probe = hdmi_audio_codec_probe,
702}; 751};
703 752
704static struct snd_soc_dai_ops hdmi_audio_codec_ops = { 753static struct snd_soc_dai_ops hdmi_audio_codec_ops = {
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index 6e63845cc7d7..d1858e71c64e 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -26,17 +26,15 @@
26#include <linux/slab.h> 26#include <linux/slab.h>
27#include <linux/module.h> 27#include <linux/module.h>
28#include <linux/platform_device.h> 28#include <linux/platform_device.h>
29#include <linux/spinlock.h>
30#include <linux/jiffies.h> 29#include <linux/jiffies.h>
31 30
32#include <video/omapdss.h> 31#include <video/omapdss.h>
33#include <plat/cpu.h>
34 32
35#include "dss.h" 33#include "dss.h"
36#include "dss_features.h" 34#include "dss_features.h"
37 35
38static int num_managers; 36static int num_managers;
39static struct list_head manager_list; 37static struct omap_overlay_manager *managers;
40 38
41static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf) 39static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf)
42{ 40{
@@ -106,7 +104,11 @@ put_device:
106static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr, 104static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr,
107 char *buf) 105 char *buf)
108{ 106{
109 return snprintf(buf, PAGE_SIZE, "%#x\n", mgr->info.default_color); 107 struct omap_overlay_manager_info info;
108
109 mgr->get_manager_info(mgr, &info);
110
111 return snprintf(buf, PAGE_SIZE, "%#x\n", info.default_color);
110} 112}
111 113
112static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr, 114static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr,
@@ -144,8 +146,11 @@ static ssize_t manager_trans_key_type_show(struct omap_overlay_manager *mgr,
144 char *buf) 146 char *buf)
145{ 147{
146 enum omap_dss_trans_key_type key_type; 148 enum omap_dss_trans_key_type key_type;
149 struct omap_overlay_manager_info info;
150
151 mgr->get_manager_info(mgr, &info);
147 152
148 key_type = mgr->info.trans_key_type; 153 key_type = info.trans_key_type;
149 BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str)); 154 BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
150 155
151 return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]); 156 return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
@@ -185,7 +190,11 @@ static ssize_t manager_trans_key_type_store(struct omap_overlay_manager *mgr,
185static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr, 190static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr,
186 char *buf) 191 char *buf)
187{ 192{
188 return snprintf(buf, PAGE_SIZE, "%#x\n", mgr->info.trans_key); 193 struct omap_overlay_manager_info info;
194
195 mgr->get_manager_info(mgr, &info);
196
197 return snprintf(buf, PAGE_SIZE, "%#x\n", info.trans_key);
189} 198}
190 199
191static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr, 200static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
@@ -217,7 +226,11 @@ static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr,
217static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr, 226static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr,
218 char *buf) 227 char *buf)
219{ 228{
220 return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_enabled); 229 struct omap_overlay_manager_info info;
230
231 mgr->get_manager_info(mgr, &info);
232
233 return snprintf(buf, PAGE_SIZE, "%d\n", info.trans_enabled);
221} 234}
222 235
223static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr, 236static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
@@ -249,10 +262,14 @@ static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr,
249static ssize_t manager_alpha_blending_enabled_show( 262static ssize_t manager_alpha_blending_enabled_show(
250 struct omap_overlay_manager *mgr, char *buf) 263 struct omap_overlay_manager *mgr, char *buf)
251{ 264{
265 struct omap_overlay_manager_info info;
266
267 mgr->get_manager_info(mgr, &info);
268
252 WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)); 269 WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
253 270
254 return snprintf(buf, PAGE_SIZE, "%d\n", 271 return snprintf(buf, PAGE_SIZE, "%d\n",
255 mgr->info.partial_alpha_enabled); 272 info.partial_alpha_enabled);
256} 273}
257 274
258static ssize_t manager_alpha_blending_enabled_store( 275static ssize_t manager_alpha_blending_enabled_store(
@@ -287,7 +304,11 @@ static ssize_t manager_alpha_blending_enabled_store(
287static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr, 304static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr,
288 char *buf) 305 char *buf)
289{ 306{
290 return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.cpr_enable); 307 struct omap_overlay_manager_info info;
308
309 mgr->get_manager_info(mgr, &info);
310
311 return snprintf(buf, PAGE_SIZE, "%d\n", info.cpr_enable);
291} 312}
292 313
293static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr, 314static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr,
@@ -469,143 +490,6 @@ static struct kobj_type manager_ktype = {
469 .default_attrs = manager_sysfs_attrs, 490 .default_attrs = manager_sysfs_attrs,
470}; 491};
471 492
472/*
473 * We have 4 levels of cache for the dispc settings. First two are in SW and
474 * the latter two in HW.
475 *
476 * +--------------------+
477 * |overlay/manager_info|
478 * +--------------------+
479 * v
480 * apply()
481 * v
482 * +--------------------+
483 * | dss_cache |
484 * +--------------------+
485 * v
486 * configure()
487 * v
488 * +--------------------+
489 * | shadow registers |
490 * +--------------------+
491 * v
492 * VFP or lcd/digit_enable
493 * v
494 * +--------------------+
495 * | registers |
496 * +--------------------+
497 */
498
499struct overlay_cache_data {
500 /* If true, cache changed, but not written to shadow registers. Set
501 * in apply(), cleared when registers written. */
502 bool dirty;
503 /* If true, shadow registers contain changed values not yet in real
504 * registers. Set when writing to shadow registers, cleared at
505 * VSYNC/EVSYNC */
506 bool shadow_dirty;
507
508 bool enabled;
509
510 struct omap_overlay_info info;
511
512 enum omap_channel channel;
513 bool replication;
514 bool ilace;
515
516 u32 fifo_low;
517 u32 fifo_high;
518};
519
520struct manager_cache_data {
521 /* If true, cache changed, but not written to shadow registers. Set
522 * in apply(), cleared when registers written. */
523 bool dirty;
524 /* If true, shadow registers contain changed values not yet in real
525 * registers. Set when writing to shadow registers, cleared at
526 * VSYNC/EVSYNC */
527 bool shadow_dirty;
528
529 struct omap_overlay_manager_info info;
530
531 bool manual_update;
532 bool do_manual_update;
533
534 /* manual update region */
535 u16 x, y, w, h;
536
537 /* enlarge the update area if the update area contains scaled
538 * overlays */
539 bool enlarge_update_area;
540};
541
542static struct {
543 spinlock_t lock;
544 struct overlay_cache_data overlay_cache[MAX_DSS_OVERLAYS];
545 struct manager_cache_data manager_cache[MAX_DSS_MANAGERS];
546
547 bool irq_enabled;
548} dss_cache;
549
550
551
552static int omap_dss_set_device(struct omap_overlay_manager *mgr,
553 struct omap_dss_device *dssdev)
554{
555 int i;
556 int r;
557
558 if (dssdev->manager) {
559 DSSERR("display '%s' already has a manager '%s'\n",
560 dssdev->name, dssdev->manager->name);
561 return -EINVAL;
562 }
563
564 if ((mgr->supported_displays & dssdev->type) == 0) {
565 DSSERR("display '%s' does not support manager '%s'\n",
566 dssdev->name, mgr->name);
567 return -EINVAL;
568 }
569
570 for (i = 0; i < mgr->num_overlays; i++) {
571 struct omap_overlay *ovl = mgr->overlays[i];
572
573 if (ovl->manager != mgr || !ovl->info.enabled)
574 continue;
575
576 r = dss_check_overlay(ovl, dssdev);
577 if (r)
578 return r;
579 }
580
581 dssdev->manager = mgr;
582 mgr->device = dssdev;
583 mgr->device_changed = true;
584
585 return 0;
586}
587
588static int omap_dss_unset_device(struct omap_overlay_manager *mgr)
589{
590 if (!mgr->device) {
591 DSSERR("failed to unset display, display not set.\n");
592 return -EINVAL;
593 }
594
595 /*
596 * Don't allow currently enabled displays to have the overlay manager
597 * pulled out from underneath them
598 */
599 if (mgr->device->state != OMAP_DSS_DISPLAY_DISABLED)
600 return -EINVAL;
601
602 mgr->device->manager = NULL;
603 mgr->device = NULL;
604 mgr->device_changed = true;
605
606 return 0;
607}
608
609static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr) 493static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
610{ 494{
611 unsigned long timeout = msecs_to_jiffies(500); 495 unsigned long timeout = msecs_to_jiffies(500);
@@ -624,1022 +508,169 @@ static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
624 return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); 508 return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
625} 509}
626 510
627static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) 511int dss_init_overlay_managers(struct platform_device *pdev)
628{
629 unsigned long timeout = msecs_to_jiffies(500);
630 struct manager_cache_data *mc;
631 u32 irq;
632 int r;
633 int i;
634 struct omap_dss_device *dssdev = mgr->device;
635
636 if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
637 return 0;
638
639 if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
640 return 0;
641
642 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
643 || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
644 irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
645 } else {
646 irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
647 DISPC_IRQ_VSYNC : DISPC_IRQ_VSYNC2;
648 }
649
650 mc = &dss_cache.manager_cache[mgr->id];
651 i = 0;
652 while (1) {
653 unsigned long flags;
654 bool shadow_dirty, dirty;
655
656 spin_lock_irqsave(&dss_cache.lock, flags);
657 dirty = mc->dirty;
658 shadow_dirty = mc->shadow_dirty;
659 spin_unlock_irqrestore(&dss_cache.lock, flags);
660
661 if (!dirty && !shadow_dirty) {
662 r = 0;
663 break;
664 }
665
666 /* 4 iterations is the worst case:
667 * 1 - initial iteration, dirty = true (between VFP and VSYNC)
668 * 2 - first VSYNC, dirty = true
669 * 3 - dirty = false, shadow_dirty = true
670 * 4 - shadow_dirty = false */
671 if (i++ == 3) {
672 DSSERR("mgr(%d)->wait_for_go() not finishing\n",
673 mgr->id);
674 r = 0;
675 break;
676 }
677
678 r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
679 if (r == -ERESTARTSYS)
680 break;
681
682 if (r) {
683 DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id);
684 break;
685 }
686 }
687
688 return r;
689}
690
691int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
692{
693 unsigned long timeout = msecs_to_jiffies(500);
694 struct overlay_cache_data *oc;
695 struct omap_dss_device *dssdev;
696 u32 irq;
697 int r;
698 int i;
699
700 if (!ovl->manager)
701 return 0;
702
703 dssdev = ovl->manager->device;
704
705 if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
706 return 0;
707
708 if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE)
709 return 0;
710
711 if (dssdev->type == OMAP_DISPLAY_TYPE_VENC
712 || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) {
713 irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
714 } else {
715 irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ?
716 DISPC_IRQ_VSYNC : DISPC_IRQ_VSYNC2;
717 }
718
719 oc = &dss_cache.overlay_cache[ovl->id];
720 i = 0;
721 while (1) {
722 unsigned long flags;
723 bool shadow_dirty, dirty;
724
725 spin_lock_irqsave(&dss_cache.lock, flags);
726 dirty = oc->dirty;
727 shadow_dirty = oc->shadow_dirty;
728 spin_unlock_irqrestore(&dss_cache.lock, flags);
729
730 if (!dirty && !shadow_dirty) {
731 r = 0;
732 break;
733 }
734
735 /* 4 iterations is the worst case:
736 * 1 - initial iteration, dirty = true (between VFP and VSYNC)
737 * 2 - first VSYNC, dirty = true
738 * 3 - dirty = false, shadow_dirty = true
739 * 4 - shadow_dirty = false */
740 if (i++ == 3) {
741 DSSERR("ovl(%d)->wait_for_go() not finishing\n",
742 ovl->id);
743 r = 0;
744 break;
745 }
746
747 r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
748 if (r == -ERESTARTSYS)
749 break;
750
751 if (r) {
752 DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id);
753 break;
754 }
755 }
756
757 return r;
758}
759
760static int overlay_enabled(struct omap_overlay *ovl)
761{
762 return ovl->info.enabled && ovl->manager && ovl->manager->device;
763}
764
765/* Is rect1 a subset of rect2? */
766static bool rectangle_subset(int x1, int y1, int w1, int h1,
767 int x2, int y2, int w2, int h2)
768{
769 if (x1 < x2 || y1 < y2)
770 return false;
771
772 if (x1 + w1 > x2 + w2)
773 return false;
774
775 if (y1 + h1 > y2 + h2)
776 return false;
777
778 return true;
779}
780
781/* Do rect1 and rect2 overlap? */
782static bool rectangle_intersects(int x1, int y1, int w1, int h1,
783 int x2, int y2, int w2, int h2)
784{
785 if (x1 >= x2 + w2)
786 return false;
787
788 if (x2 >= x1 + w1)
789 return false;
790
791 if (y1 >= y2 + h2)
792 return false;
793
794 if (y2 >= y1 + h1)
795 return false;
796
797 return true;
798}
799
800static bool dispc_is_overlay_scaled(struct overlay_cache_data *oc)
801{
802 struct omap_overlay_info *oi = &oc->info;
803
804 if (oi->out_width != 0 && oi->width != oi->out_width)
805 return true;
806
807 if (oi->out_height != 0 && oi->height != oi->out_height)
808 return true;
809
810 return false;
811}
812
813static int configure_overlay(enum omap_plane plane)
814{ 512{
815 struct overlay_cache_data *c; 513 int i, r;
816 struct manager_cache_data *mc;
817 struct omap_overlay_info *oi, new_oi;
818 struct omap_overlay_manager_info *mi;
819 u16 outw, outh;
820 u16 x, y, w, h;
821 u32 paddr;
822 int r;
823 u16 orig_w, orig_h, orig_outw, orig_outh;
824 514
825 DSSDBGF("%d", plane); 515 num_managers = dss_feat_get_num_mgrs();
826 516
827 c = &dss_cache.overlay_cache[plane]; 517 managers = kzalloc(sizeof(struct omap_overlay_manager) * num_managers,
828 oi = &c->info; 518 GFP_KERNEL);
829 519
830 if (!c->enabled) { 520 BUG_ON(managers == NULL);
831 dispc_ovl_enable(plane, 0);
832 return 0;
833 }
834 521
835 mc = &dss_cache.manager_cache[c->channel]; 522 for (i = 0; i < num_managers; ++i) {
836 mi = &mc->info; 523 struct omap_overlay_manager *mgr = &managers[i];
837
838 x = oi->pos_x;
839 y = oi->pos_y;
840 w = oi->width;
841 h = oi->height;
842 outw = oi->out_width == 0 ? oi->width : oi->out_width;
843 outh = oi->out_height == 0 ? oi->height : oi->out_height;
844 paddr = oi->paddr;
845
846 orig_w = w;
847 orig_h = h;
848 orig_outw = outw;
849 orig_outh = outh;
850
851 if (mc->manual_update && mc->do_manual_update) {
852 unsigned bpp;
853 unsigned scale_x_m = w, scale_x_d = outw;
854 unsigned scale_y_m = h, scale_y_d = outh;
855
856 /* If the overlay is outside the update region, disable it */
857 if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h,
858 x, y, outw, outh)) {
859 dispc_ovl_enable(plane, 0);
860 return 0;
861 }
862 524
863 switch (oi->color_mode) { 525 switch (i) {
864 case OMAP_DSS_COLOR_NV12: 526 case 0:
865 bpp = 8; 527 mgr->name = "lcd";
866 break; 528 mgr->id = OMAP_DSS_CHANNEL_LCD;
867 case OMAP_DSS_COLOR_RGB16:
868 case OMAP_DSS_COLOR_ARGB16:
869 case OMAP_DSS_COLOR_YUV2:
870 case OMAP_DSS_COLOR_UYVY:
871 case OMAP_DSS_COLOR_RGBA16:
872 case OMAP_DSS_COLOR_RGBX16:
873 case OMAP_DSS_COLOR_ARGB16_1555:
874 case OMAP_DSS_COLOR_XRGB16_1555:
875 bpp = 16;
876 break; 529 break;
877 530 case 1:
878 case OMAP_DSS_COLOR_RGB24P: 531 mgr->name = "tv";
879 bpp = 24; 532 mgr->id = OMAP_DSS_CHANNEL_DIGIT;
880 break; 533 break;
881 534 case 2:
882 case OMAP_DSS_COLOR_RGB24U: 535 mgr->name = "lcd2";
883 case OMAP_DSS_COLOR_ARGB32: 536 mgr->id = OMAP_DSS_CHANNEL_LCD2;
884 case OMAP_DSS_COLOR_RGBA32:
885 case OMAP_DSS_COLOR_RGBX32:
886 bpp = 32;
887 break; 537 break;
888
889 default:
890 BUG();
891 } 538 }
892 539
893 if (mc->x > oi->pos_x) { 540 mgr->set_device = &dss_mgr_set_device;
894 x = 0; 541 mgr->unset_device = &dss_mgr_unset_device;
895 outw -= (mc->x - oi->pos_x); 542 mgr->apply = &omap_dss_mgr_apply;
896 paddr += (mc->x - oi->pos_x) * 543 mgr->set_manager_info = &dss_mgr_set_info;
897 scale_x_m / scale_x_d * bpp / 8; 544 mgr->get_manager_info = &dss_mgr_get_info;
898 } else { 545 mgr->wait_for_go = &dss_mgr_wait_for_go;
899 x = oi->pos_x - mc->x; 546 mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
900 }
901
902 if (mc->y > oi->pos_y) {
903 y = 0;
904 outh -= (mc->y - oi->pos_y);
905 paddr += (mc->y - oi->pos_y) *
906 scale_y_m / scale_y_d *
907 oi->screen_width * bpp / 8;
908 } else {
909 y = oi->pos_y - mc->y;
910 }
911
912 if (mc->w < (x + outw))
913 outw -= (x + outw) - (mc->w);
914
915 if (mc->h < (y + outh))
916 outh -= (y + outh) - (mc->h);
917
918 w = w * outw / orig_outw;
919 h = h * outh / orig_outh;
920
921 /* YUV mode overlay's input width has to be even and the
922 * algorithm above may adjust the width to be odd.
923 *
924 * Here we adjust the width if needed, preferring to increase
925 * the width if the original width was bigger.
926 */
927 if ((w & 1) &&
928 (oi->color_mode == OMAP_DSS_COLOR_YUV2 ||
929 oi->color_mode == OMAP_DSS_COLOR_UYVY)) {
930 if (orig_w > w)
931 w += 1;
932 else
933 w -= 1;
934 }
935 }
936
937 new_oi = *oi;
938
939 /* update new_oi members which could have been possibly updated */
940 new_oi.pos_x = x;
941 new_oi.pos_y = y;
942 new_oi.width = w;
943 new_oi.height = h;
944 new_oi.out_width = outw;
945 new_oi.out_height = outh;
946 new_oi.paddr = paddr;
947
948 r = dispc_ovl_setup(plane, &new_oi, c->ilace, c->channel,
949 c->replication, c->fifo_low, c->fifo_high);
950 if (r) {
951 /* this shouldn't happen */
952 DSSERR("dispc_ovl_setup failed for ovl %d\n", plane);
953 dispc_ovl_enable(plane, 0);
954 return r;
955 }
956
957 dispc_ovl_enable(plane, 1);
958
959 return 0;
960}
961
962static void configure_manager(enum omap_channel channel)
963{
964 struct omap_overlay_manager_info *mi;
965
966 DSSDBGF("%d", channel);
967
968 /* picking info from the cache */
969 mi = &dss_cache.manager_cache[channel].info;
970
971 dispc_mgr_set_default_color(channel, mi->default_color);
972 dispc_mgr_set_trans_key(channel, mi->trans_key_type, mi->trans_key);
973 dispc_mgr_enable_trans_key(channel, mi->trans_enabled);
974 dispc_mgr_enable_alpha_fixed_zorder(channel, mi->partial_alpha_enabled);
975 if (dss_has_feature(FEAT_CPR)) {
976 dispc_mgr_enable_cpr(channel, mi->cpr_enable);
977 dispc_mgr_set_cpr_coef(channel, &mi->cpr_coefs);
978 }
979}
980
981/* configure_dispc() tries to write values from cache to shadow registers.
982 * It writes only to those managers/overlays that are not busy.
983 * returns 0 if everything could be written to shadow registers.
984 * returns 1 if not everything could be written to shadow registers. */
985static int configure_dispc(void)
986{
987 struct overlay_cache_data *oc;
988 struct manager_cache_data *mc;
989 const int num_ovls = dss_feat_get_num_ovls();
990 const int num_mgrs = dss_feat_get_num_mgrs();
991 int i;
992 int r;
993 bool mgr_busy[MAX_DSS_MANAGERS];
994 bool mgr_go[MAX_DSS_MANAGERS];
995 bool busy;
996
997 r = 0;
998 busy = false;
999
1000 for (i = 0; i < num_mgrs; i++) {
1001 mgr_busy[i] = dispc_mgr_go_busy(i);
1002 mgr_go[i] = false;
1003 }
1004
1005 /* Commit overlay settings */
1006 for (i = 0; i < num_ovls; ++i) {
1007 oc = &dss_cache.overlay_cache[i];
1008 mc = &dss_cache.manager_cache[oc->channel];
1009 547
1010 if (!oc->dirty) 548 mgr->caps = 0;
1011 continue; 549 mgr->supported_displays =
550 dss_feat_get_supported_displays(mgr->id);
1012 551
1013 if (mc->manual_update && !mc->do_manual_update) 552 INIT_LIST_HEAD(&mgr->overlays);
1014 continue;
1015 553
1016 if (mgr_busy[oc->channel]) { 554 r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
1017 busy = true; 555 &pdev->dev.kobj, "manager%d", i);
1018 continue;
1019 }
1020 556
1021 r = configure_overlay(i);
1022 if (r) 557 if (r)
1023 DSSERR("configure_overlay %d failed\n", i); 558 DSSERR("failed to create sysfs file\n");
1024
1025 oc->dirty = false;
1026 oc->shadow_dirty = true;
1027 mgr_go[oc->channel] = true;
1028 }
1029
1030 /* Commit manager settings */
1031 for (i = 0; i < num_mgrs; ++i) {
1032 mc = &dss_cache.manager_cache[i];
1033
1034 if (!mc->dirty)
1035 continue;
1036
1037 if (mc->manual_update && !mc->do_manual_update)
1038 continue;
1039
1040 if (mgr_busy[i]) {
1041 busy = true;
1042 continue;
1043 }
1044
1045 configure_manager(i);
1046 mc->dirty = false;
1047 mc->shadow_dirty = true;
1048 mgr_go[i] = true;
1049 }
1050
1051 /* set GO */
1052 for (i = 0; i < num_mgrs; ++i) {
1053 mc = &dss_cache.manager_cache[i];
1054
1055 if (!mgr_go[i])
1056 continue;
1057
1058 /* We don't need GO with manual update display. LCD iface will
1059 * always be turned off after frame, and new settings will be
1060 * taken in to use at next update */
1061 if (!mc->manual_update)
1062 dispc_mgr_go(i);
1063 }
1064
1065 if (busy)
1066 r = 1;
1067 else
1068 r = 0;
1069
1070 return r;
1071}
1072
1073/* Make the coordinates even. There are some strange problems with OMAP and
1074 * partial DSI update when the update widths are odd. */
1075static void make_even(u16 *x, u16 *w)
1076{
1077 u16 x1, x2;
1078
1079 x1 = *x;
1080 x2 = *x + *w;
1081
1082 x1 &= ~1;
1083 x2 = ALIGN(x2, 2);
1084
1085 *x = x1;
1086 *w = x2 - x1;
1087}
1088
1089/* Configure dispc for partial update. Return possibly modified update
1090 * area */
1091void dss_setup_partial_planes(struct omap_dss_device *dssdev,
1092 u16 *xi, u16 *yi, u16 *wi, u16 *hi, bool enlarge_update_area)
1093{
1094 struct overlay_cache_data *oc;
1095 struct manager_cache_data *mc;
1096 struct omap_overlay_info *oi;
1097 const int num_ovls = dss_feat_get_num_ovls();
1098 struct omap_overlay_manager *mgr;
1099 int i;
1100 u16 x, y, w, h;
1101 unsigned long flags;
1102 bool area_changed;
1103
1104 x = *xi;
1105 y = *yi;
1106 w = *wi;
1107 h = *hi;
1108
1109 DSSDBG("dispc_setup_partial_planes %d,%d %dx%d\n",
1110 *xi, *yi, *wi, *hi);
1111
1112 mgr = dssdev->manager;
1113
1114 if (!mgr) {
1115 DSSDBG("no manager\n");
1116 return;
1117 } 559 }
1118 560
1119 make_even(&x, &w); 561 return 0;
1120
1121 spin_lock_irqsave(&dss_cache.lock, flags);
1122
1123 /*
1124 * Execute the outer loop until the inner loop has completed
1125 * once without increasing the update area. This will ensure that
1126 * all scaled overlays end up completely within the update area.
1127 */
1128 do {
1129 area_changed = false;
1130
1131 /* We need to show the whole overlay if it is scaled. So look
1132 * for those, and make the update area larger if found.
1133 * Also mark the overlay cache dirty */
1134 for (i = 0; i < num_ovls; ++i) {
1135 unsigned x1, y1, x2, y2;
1136 unsigned outw, outh;
1137
1138 oc = &dss_cache.overlay_cache[i];
1139 oi = &oc->info;
1140
1141 if (oc->channel != mgr->id)
1142 continue;
1143
1144 oc->dirty = true;
1145
1146 if (!enlarge_update_area)
1147 continue;
1148
1149 if (!oc->enabled)
1150 continue;
1151
1152 if (!dispc_is_overlay_scaled(oc))
1153 continue;
1154
1155 outw = oi->out_width == 0 ?
1156 oi->width : oi->out_width;
1157 outh = oi->out_height == 0 ?
1158 oi->height : oi->out_height;
1159
1160 /* is the overlay outside the update region? */
1161 if (!rectangle_intersects(x, y, w, h,
1162 oi->pos_x, oi->pos_y,
1163 outw, outh))
1164 continue;
1165
1166 /* if the overlay totally inside the update region? */
1167 if (rectangle_subset(oi->pos_x, oi->pos_y, outw, outh,
1168 x, y, w, h))
1169 continue;
1170
1171 if (x > oi->pos_x)
1172 x1 = oi->pos_x;
1173 else
1174 x1 = x;
1175
1176 if (y > oi->pos_y)
1177 y1 = oi->pos_y;
1178 else
1179 y1 = y;
1180
1181 if ((x + w) < (oi->pos_x + outw))
1182 x2 = oi->pos_x + outw;
1183 else
1184 x2 = x + w;
1185
1186 if ((y + h) < (oi->pos_y + outh))
1187 y2 = oi->pos_y + outh;
1188 else
1189 y2 = y + h;
1190
1191 x = x1;
1192 y = y1;
1193 w = x2 - x1;
1194 h = y2 - y1;
1195
1196 make_even(&x, &w);
1197
1198 DSSDBG("changing upd area due to ovl(%d) "
1199 "scaling %d,%d %dx%d\n",
1200 i, x, y, w, h);
1201
1202 area_changed = true;
1203 }
1204 } while (area_changed);
1205
1206 mc = &dss_cache.manager_cache[mgr->id];
1207 mc->do_manual_update = true;
1208 mc->enlarge_update_area = enlarge_update_area;
1209 mc->x = x;
1210 mc->y = y;
1211 mc->w = w;
1212 mc->h = h;
1213
1214 configure_dispc();
1215
1216 mc->do_manual_update = false;
1217
1218 spin_unlock_irqrestore(&dss_cache.lock, flags);
1219
1220 *xi = x;
1221 *yi = y;
1222 *wi = w;
1223 *hi = h;
1224} 562}
1225 563
1226void dss_start_update(struct omap_dss_device *dssdev) 564void dss_uninit_overlay_managers(struct platform_device *pdev)
1227{ 565{
1228 struct manager_cache_data *mc;
1229 struct overlay_cache_data *oc;
1230 const int num_ovls = dss_feat_get_num_ovls();
1231 const int num_mgrs = dss_feat_get_num_mgrs();
1232 struct omap_overlay_manager *mgr;
1233 int i; 566 int i;
1234 567
1235 mgr = dssdev->manager; 568 for (i = 0; i < num_managers; ++i) {
569 struct omap_overlay_manager *mgr = &managers[i];
1236 570
1237 for (i = 0; i < num_ovls; ++i) { 571 kobject_del(&mgr->kobj);
1238 oc = &dss_cache.overlay_cache[i]; 572 kobject_put(&mgr->kobj);
1239 if (oc->channel != mgr->id)
1240 continue;
1241
1242 oc->shadow_dirty = false;
1243 }
1244
1245 for (i = 0; i < num_mgrs; ++i) {
1246 mc = &dss_cache.manager_cache[i];
1247 if (mgr->id != i)
1248 continue;
1249
1250 mc->shadow_dirty = false;
1251 } 573 }
1252 574
1253 dssdev->manager->enable(dssdev->manager); 575 kfree(managers);
576 managers = NULL;
577 num_managers = 0;
1254} 578}
1255 579
1256static void dss_apply_irq_handler(void *data, u32 mask) 580int omap_dss_get_num_overlay_managers(void)
1257{ 581{
1258 struct manager_cache_data *mc; 582 return num_managers;
1259 struct overlay_cache_data *oc;
1260 const int num_ovls = dss_feat_get_num_ovls();
1261 const int num_mgrs = dss_feat_get_num_mgrs();
1262 int i, r;
1263 bool mgr_busy[MAX_DSS_MANAGERS];
1264 u32 irq_mask;
1265
1266 for (i = 0; i < num_mgrs; i++)
1267 mgr_busy[i] = dispc_mgr_go_busy(i);
1268
1269 spin_lock(&dss_cache.lock);
1270
1271 for (i = 0; i < num_ovls; ++i) {
1272 oc = &dss_cache.overlay_cache[i];
1273 if (!mgr_busy[oc->channel])
1274 oc->shadow_dirty = false;
1275 }
1276
1277 for (i = 0; i < num_mgrs; ++i) {
1278 mc = &dss_cache.manager_cache[i];
1279 if (!mgr_busy[i])
1280 mc->shadow_dirty = false;
1281 }
1282
1283 r = configure_dispc();
1284 if (r == 1)
1285 goto end;
1286
1287 /* re-read busy flags */
1288 for (i = 0; i < num_mgrs; i++)
1289 mgr_busy[i] = dispc_mgr_go_busy(i);
1290
1291 /* keep running as long as there are busy managers, so that
1292 * we can collect overlay-applied information */
1293 for (i = 0; i < num_mgrs; ++i) {
1294 if (mgr_busy[i])
1295 goto end;
1296 }
1297
1298 irq_mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD |
1299 DISPC_IRQ_EVSYNC_EVEN;
1300 if (dss_has_feature(FEAT_MGR_LCD2))
1301 irq_mask |= DISPC_IRQ_VSYNC2;
1302
1303 omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, irq_mask);
1304 dss_cache.irq_enabled = false;
1305
1306end:
1307 spin_unlock(&dss_cache.lock);
1308} 583}
584EXPORT_SYMBOL(omap_dss_get_num_overlay_managers);
1309 585
1310static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) 586struct omap_overlay_manager *omap_dss_get_overlay_manager(int num)
1311{ 587{
1312 struct overlay_cache_data *oc; 588 if (num >= num_managers)
1313 struct manager_cache_data *mc; 589 return NULL;
1314 int i;
1315 struct omap_overlay *ovl;
1316 int num_planes_enabled = 0;
1317 bool use_fifomerge;
1318 unsigned long flags;
1319 int r;
1320
1321 DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name);
1322
1323 r = dispc_runtime_get();
1324 if (r)
1325 return r;
1326
1327 spin_lock_irqsave(&dss_cache.lock, flags);
1328
1329 /* Configure overlays */
1330 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
1331 struct omap_dss_device *dssdev;
1332
1333 ovl = omap_dss_get_overlay(i);
1334
1335 oc = &dss_cache.overlay_cache[ovl->id];
1336
1337 if (ovl->manager_changed) {
1338 ovl->manager_changed = false;
1339 ovl->info_dirty = true;
1340 }
1341
1342 if (!overlay_enabled(ovl)) {
1343 if (oc->enabled) {
1344 oc->enabled = false;
1345 oc->dirty = true;
1346 }
1347 continue;
1348 }
1349
1350 if (!ovl->info_dirty) {
1351 if (oc->enabled)
1352 ++num_planes_enabled;
1353 continue;
1354 }
1355
1356 dssdev = ovl->manager->device;
1357
1358 if (dss_check_overlay(ovl, dssdev)) {
1359 if (oc->enabled) {
1360 oc->enabled = false;
1361 oc->dirty = true;
1362 }
1363 continue;
1364 }
1365
1366 ovl->info_dirty = false;
1367 oc->dirty = true;
1368 oc->info = ovl->info;
1369
1370 oc->replication =
1371 dss_use_replication(dssdev, ovl->info.color_mode);
1372
1373 oc->ilace = dssdev->type == OMAP_DISPLAY_TYPE_VENC;
1374
1375 oc->channel = ovl->manager->id;
1376
1377 oc->enabled = true;
1378
1379 ++num_planes_enabled;
1380 }
1381
1382 /* Configure managers */
1383 list_for_each_entry(mgr, &manager_list, list) {
1384 struct omap_dss_device *dssdev;
1385 590
1386 mc = &dss_cache.manager_cache[mgr->id]; 591 return &managers[num];
1387
1388 if (mgr->device_changed) {
1389 mgr->device_changed = false;
1390 mgr->info_dirty = true;
1391 }
1392
1393 if (!mgr->info_dirty)
1394 continue;
1395
1396 if (!mgr->device)
1397 continue;
1398
1399 dssdev = mgr->device;
1400
1401 mgr->info_dirty = false;
1402 mc->dirty = true;
1403 mc->info = mgr->info;
1404
1405 mc->manual_update =
1406 dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
1407 }
1408
1409 /* XXX TODO: Try to get fifomerge working. The problem is that it
1410 * affects both managers, not individually but at the same time. This
1411 * means the change has to be well synchronized. I guess the proper way
1412 * is to have a two step process for fifo merge:
1413 * fifomerge enable:
1414 * 1. disable other planes, leaving one plane enabled
1415 * 2. wait until the planes are disabled on HW
1416 * 3. config merged fifo thresholds, enable fifomerge
1417 * fifomerge disable:
1418 * 1. config unmerged fifo thresholds, disable fifomerge
1419 * 2. wait until fifo changes are in HW
1420 * 3. enable planes
1421 */
1422 use_fifomerge = false;
1423
1424 /* Configure overlay fifos */
1425 for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
1426 struct omap_dss_device *dssdev;
1427 u32 size, burst_size;
1428
1429 ovl = omap_dss_get_overlay(i);
1430
1431 oc = &dss_cache.overlay_cache[ovl->id];
1432
1433 if (!oc->enabled)
1434 continue;
1435
1436 dssdev = ovl->manager->device;
1437
1438 size = dispc_ovl_get_fifo_size(ovl->id);
1439 if (use_fifomerge)
1440 size *= 3;
1441
1442 burst_size = dispc_ovl_get_burst_size(ovl->id);
1443
1444 switch (dssdev->type) {
1445 case OMAP_DISPLAY_TYPE_DPI:
1446 case OMAP_DISPLAY_TYPE_DBI:
1447 case OMAP_DISPLAY_TYPE_SDI:
1448 case OMAP_DISPLAY_TYPE_VENC:
1449 case OMAP_DISPLAY_TYPE_HDMI:
1450 default_get_overlay_fifo_thresholds(ovl->id, size,
1451 burst_size, &oc->fifo_low,
1452 &oc->fifo_high);
1453 break;
1454#ifdef CONFIG_OMAP2_DSS_DSI
1455 case OMAP_DISPLAY_TYPE_DSI:
1456 dsi_get_overlay_fifo_thresholds(ovl->id, size,
1457 burst_size, &oc->fifo_low,
1458 &oc->fifo_high);
1459 break;
1460#endif
1461 default:
1462 BUG();
1463 }
1464 }
1465
1466 r = 0;
1467 if (!dss_cache.irq_enabled) {
1468 u32 mask;
1469
1470 mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD |
1471 DISPC_IRQ_EVSYNC_EVEN;
1472 if (dss_has_feature(FEAT_MGR_LCD2))
1473 mask |= DISPC_IRQ_VSYNC2;
1474
1475 r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, mask);
1476 dss_cache.irq_enabled = true;
1477 }
1478 configure_dispc();
1479
1480 spin_unlock_irqrestore(&dss_cache.lock, flags);
1481
1482 dispc_runtime_put();
1483
1484 return r;
1485} 592}
593EXPORT_SYMBOL(omap_dss_get_overlay_manager);
1486 594
1487static int dss_check_manager(struct omap_overlay_manager *mgr) 595int dss_mgr_simple_check(struct omap_overlay_manager *mgr,
596 const struct omap_overlay_manager_info *info)
1488{ 597{
1489 if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) { 598 if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) {
1490 /* 599 /*
1491 * OMAP3 supports only graphics source transparency color key 600 * OMAP3 supports only graphics source transparency color key
1492 * and alpha blending simultaneously. See TRM 15.4.2.4.2.2 601 * and alpha blending simultaneously. See TRM 15.4.2.4.2.2
1493 * Alpha Mode 602 * Alpha Mode.
1494 */ 603 */
1495 if (mgr->info.partial_alpha_enabled && mgr->info.trans_enabled 604 if (info->partial_alpha_enabled && info->trans_enabled
1496 && mgr->info.trans_key_type != 605 && info->trans_key_type != OMAP_DSS_COLOR_KEY_GFX_DST) {
1497 OMAP_DSS_COLOR_KEY_GFX_DST) 606 DSSERR("check_manager: illegal transparency key\n");
1498 return -EINVAL; 607 return -EINVAL;
608 }
1499 } 609 }
1500 610
1501 return 0; 611 return 0;
1502} 612}
1503 613
1504static int omap_dss_mgr_set_info(struct omap_overlay_manager *mgr, 614static int dss_mgr_check_zorder(struct omap_overlay_manager *mgr,
1505 struct omap_overlay_manager_info *info) 615 struct omap_overlay_info **overlay_infos)
1506{
1507 int r;
1508 struct omap_overlay_manager_info old_info;
1509
1510 old_info = mgr->info;
1511 mgr->info = *info;
1512
1513 r = dss_check_manager(mgr);
1514 if (r) {
1515 mgr->info = old_info;
1516 return r;
1517 }
1518
1519 mgr->info_dirty = true;
1520
1521 return 0;
1522}
1523
1524static void omap_dss_mgr_get_info(struct omap_overlay_manager *mgr,
1525 struct omap_overlay_manager_info *info)
1526{ 616{
1527 *info = mgr->info; 617 struct omap_overlay *ovl1, *ovl2;
1528} 618 struct omap_overlay_info *info1, *info2;
1529 619
1530static int dss_mgr_enable(struct omap_overlay_manager *mgr) 620 list_for_each_entry(ovl1, &mgr->overlays, list) {
1531{ 621 info1 = overlay_infos[ovl1->id];
1532 dispc_mgr_enable(mgr->id, 1);
1533 return 0;
1534}
1535 622
1536static int dss_mgr_disable(struct omap_overlay_manager *mgr) 623 if (info1 == NULL)
1537{ 624 continue;
1538 dispc_mgr_enable(mgr->id, 0);
1539 return 0;
1540}
1541
1542static void omap_dss_add_overlay_manager(struct omap_overlay_manager *manager)
1543{
1544 ++num_managers;
1545 list_add_tail(&manager->list, &manager_list);
1546}
1547
1548int dss_init_overlay_managers(struct platform_device *pdev)
1549{
1550 int i, r;
1551
1552 spin_lock_init(&dss_cache.lock);
1553
1554 INIT_LIST_HEAD(&manager_list);
1555
1556 num_managers = 0;
1557
1558 for (i = 0; i < dss_feat_get_num_mgrs(); ++i) {
1559 struct omap_overlay_manager *mgr;
1560 mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
1561
1562 BUG_ON(mgr == NULL);
1563
1564 switch (i) {
1565 case 0:
1566 mgr->name = "lcd";
1567 mgr->id = OMAP_DSS_CHANNEL_LCD;
1568 break;
1569 case 1:
1570 mgr->name = "tv";
1571 mgr->id = OMAP_DSS_CHANNEL_DIGIT;
1572 break;
1573 case 2:
1574 mgr->name = "lcd2";
1575 mgr->id = OMAP_DSS_CHANNEL_LCD2;
1576 break;
1577 }
1578
1579 mgr->set_device = &omap_dss_set_device;
1580 mgr->unset_device = &omap_dss_unset_device;
1581 mgr->apply = &omap_dss_mgr_apply;
1582 mgr->set_manager_info = &omap_dss_mgr_set_info;
1583 mgr->get_manager_info = &omap_dss_mgr_get_info;
1584 mgr->wait_for_go = &dss_mgr_wait_for_go;
1585 mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
1586
1587 mgr->enable = &dss_mgr_enable;
1588 mgr->disable = &dss_mgr_disable;
1589
1590 mgr->caps = 0;
1591 mgr->supported_displays =
1592 dss_feat_get_supported_displays(mgr->id);
1593 625
1594 dss_overlay_setup_dispc_manager(mgr); 626 list_for_each_entry(ovl2, &mgr->overlays, list) {
627 if (ovl1 == ovl2)
628 continue;
1595 629
1596 omap_dss_add_overlay_manager(mgr); 630 info2 = overlay_infos[ovl2->id];
1597 631
1598 r = kobject_init_and_add(&mgr->kobj, &manager_ktype, 632 if (info2 == NULL)
1599 &pdev->dev.kobj, "manager%d", i); 633 continue;
1600 634
1601 if (r) { 635 if (info1->zorder == info2->zorder) {
1602 DSSERR("failed to create sysfs file\n"); 636 DSSERR("overlays %d and %d have the same "
1603 continue; 637 "zorder %d\n",
638 ovl1->id, ovl2->id, info1->zorder);
639 return -EINVAL;
640 }
1604 } 641 }
1605 } 642 }
1606 643
1607 return 0; 644 return 0;
1608} 645}
1609 646
1610void dss_uninit_overlay_managers(struct platform_device *pdev) 647int dss_mgr_check(struct omap_overlay_manager *mgr,
648 struct omap_dss_device *dssdev,
649 struct omap_overlay_manager_info *info,
650 struct omap_overlay_info **overlay_infos)
1611{ 651{
1612 struct omap_overlay_manager *mgr; 652 struct omap_overlay *ovl;
653 int r;
1613 654
1614 while (!list_empty(&manager_list)) { 655 if (dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) {
1615 mgr = list_first_entry(&manager_list, 656 r = dss_mgr_check_zorder(mgr, overlay_infos);
1616 struct omap_overlay_manager, list); 657 if (r)
1617 list_del(&mgr->list); 658 return r;
1618 kobject_del(&mgr->kobj);
1619 kobject_put(&mgr->kobj);
1620 kfree(mgr);
1621 } 659 }
1622 660
1623 num_managers = 0; 661 list_for_each_entry(ovl, &mgr->overlays, list) {
1624} 662 struct omap_overlay_info *oi;
663 int r;
1625 664
1626int omap_dss_get_num_overlay_managers(void) 665 oi = overlay_infos[ovl->id];
1627{
1628 return num_managers;
1629}
1630EXPORT_SYMBOL(omap_dss_get_num_overlay_managers);
1631 666
1632struct omap_overlay_manager *omap_dss_get_overlay_manager(int num) 667 if (oi == NULL)
1633{ 668 continue;
1634 int i = 0;
1635 struct omap_overlay_manager *mgr;
1636 669
1637 list_for_each_entry(mgr, &manager_list, list) { 670 r = dss_ovl_check(ovl, oi, dssdev);
1638 if (i++ == num) 671 if (r)
1639 return mgr; 672 return r;
1640 } 673 }
1641 674
1642 return NULL; 675 return 0;
1643} 676}
1644EXPORT_SYMBOL(omap_dss_get_overlay_manager);
1645
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index ab8e40e48759..6e821810deec 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -38,7 +38,7 @@
38#include "dss_features.h" 38#include "dss_features.h"
39 39
40static int num_overlays; 40static int num_overlays;
41static struct list_head overlay_list; 41static struct omap_overlay *overlays;
42 42
43static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf) 43static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
44{ 44{
@@ -124,19 +124,31 @@ err:
124 124
125static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf) 125static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
126{ 126{
127 struct omap_overlay_info info;
128
129 ovl->get_overlay_info(ovl, &info);
130
127 return snprintf(buf, PAGE_SIZE, "%d,%d\n", 131 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
128 ovl->info.width, ovl->info.height); 132 info.width, info.height);
129} 133}
130 134
131static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf) 135static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
132{ 136{
133 return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.screen_width); 137 struct omap_overlay_info info;
138
139 ovl->get_overlay_info(ovl, &info);
140
141 return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width);
134} 142}
135 143
136static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf) 144static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
137{ 145{
146 struct omap_overlay_info info;
147
148 ovl->get_overlay_info(ovl, &info);
149
138 return snprintf(buf, PAGE_SIZE, "%d,%d\n", 150 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
139 ovl->info.pos_x, ovl->info.pos_y); 151 info.pos_x, info.pos_y);
140} 152}
141 153
142static ssize_t overlay_position_store(struct omap_overlay *ovl, 154static ssize_t overlay_position_store(struct omap_overlay *ovl,
@@ -170,8 +182,12 @@ static ssize_t overlay_position_store(struct omap_overlay *ovl,
170 182
171static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf) 183static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
172{ 184{
185 struct omap_overlay_info info;
186
187 ovl->get_overlay_info(ovl, &info);
188
173 return snprintf(buf, PAGE_SIZE, "%d,%d\n", 189 return snprintf(buf, PAGE_SIZE, "%d,%d\n",
174 ovl->info.out_width, ovl->info.out_height); 190 info.out_width, info.out_height);
175} 191}
176 192
177static ssize_t overlay_output_size_store(struct omap_overlay *ovl, 193static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
@@ -205,7 +221,7 @@ static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
205 221
206static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf) 222static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
207{ 223{
208 return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.enabled); 224 return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl));
209} 225}
210 226
211static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf, 227static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
@@ -213,33 +229,30 @@ static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
213{ 229{
214 int r; 230 int r;
215 bool enable; 231 bool enable;
216 struct omap_overlay_info info;
217
218 ovl->get_overlay_info(ovl, &info);
219 232
220 r = strtobool(buf, &enable); 233 r = strtobool(buf, &enable);
221 if (r) 234 if (r)
222 return r; 235 return r;
223 236
224 info.enabled = enable; 237 if (enable)
238 r = ovl->enable(ovl);
239 else
240 r = ovl->disable(ovl);
225 241
226 r = ovl->set_overlay_info(ovl, &info);
227 if (r) 242 if (r)
228 return r; 243 return r;
229 244
230 if (ovl->manager) {
231 r = ovl->manager->apply(ovl->manager);
232 if (r)
233 return r;
234 }
235
236 return size; 245 return size;
237} 246}
238 247
239static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf) 248static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
240{ 249{
250 struct omap_overlay_info info;
251
252 ovl->get_overlay_info(ovl, &info);
253
241 return snprintf(buf, PAGE_SIZE, "%d\n", 254 return snprintf(buf, PAGE_SIZE, "%d\n",
242 ovl->info.global_alpha); 255 info.global_alpha);
243} 256}
244 257
245static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl, 258static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
@@ -276,8 +289,12 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
276static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl, 289static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
277 char *buf) 290 char *buf)
278{ 291{
292 struct omap_overlay_info info;
293
294 ovl->get_overlay_info(ovl, &info);
295
279 return snprintf(buf, PAGE_SIZE, "%d\n", 296 return snprintf(buf, PAGE_SIZE, "%d\n",
280 ovl->info.pre_mult_alpha); 297 info.pre_mult_alpha);
281} 298}
282 299
283static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl, 300static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
@@ -313,7 +330,11 @@ static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
313 330
314static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf) 331static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
315{ 332{
316 return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.zorder); 333 struct omap_overlay_info info;
334
335 ovl->get_overlay_info(ovl, &info);
336
337 return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder);
317} 338}
318 339
319static ssize_t overlay_zorder_store(struct omap_overlay *ovl, 340static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
@@ -430,183 +451,6 @@ static struct kobj_type overlay_ktype = {
430 .default_attrs = overlay_sysfs_attrs, 451 .default_attrs = overlay_sysfs_attrs,
431}; 452};
432 453
433/* Check if overlay parameters are compatible with display */
434int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev)
435{
436 struct omap_overlay_info *info;
437 u16 outw, outh;
438 u16 dw, dh;
439 int i;
440
441 if (!dssdev)
442 return 0;
443
444 if (!ovl->info.enabled)
445 return 0;
446
447 info = &ovl->info;
448
449 if (info->paddr == 0) {
450 DSSDBG("check_overlay failed: paddr 0\n");
451 return -EINVAL;
452 }
453
454 dssdev->driver->get_resolution(dssdev, &dw, &dh);
455
456 DSSDBG("check_overlay %d: (%d,%d %dx%d -> %dx%d) disp (%dx%d)\n",
457 ovl->id,
458 info->pos_x, info->pos_y,
459 info->width, info->height,
460 info->out_width, info->out_height,
461 dw, dh);
462
463 if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
464 outw = info->width;
465 outh = info->height;
466 } else {
467 if (info->out_width == 0)
468 outw = info->width;
469 else
470 outw = info->out_width;
471
472 if (info->out_height == 0)
473 outh = info->height;
474 else
475 outh = info->out_height;
476 }
477
478 if (dw < info->pos_x + outw) {
479 DSSDBG("check_overlay failed 1: %d < %d + %d\n",
480 dw, info->pos_x, outw);
481 return -EINVAL;
482 }
483
484 if (dh < info->pos_y + outh) {
485 DSSDBG("check_overlay failed 2: %d < %d + %d\n",
486 dh, info->pos_y, outh);
487 return -EINVAL;
488 }
489
490 if ((ovl->supported_modes & info->color_mode) == 0) {
491 DSSERR("overlay doesn't support mode %d\n", info->color_mode);
492 return -EINVAL;
493 }
494
495 if (ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) {
496 if (info->zorder < 0 || info->zorder > 3) {
497 DSSERR("zorder out of range: %d\n",
498 info->zorder);
499 return -EINVAL;
500 }
501 /*
502 * Check that zorder doesn't match with zorder of any other
503 * overlay which is enabled and is also connected to the same
504 * manager
505 */
506 for (i = 0; i < omap_dss_get_num_overlays(); i++) {
507 struct omap_overlay *tmp_ovl = omap_dss_get_overlay(i);
508
509 if (tmp_ovl->id != ovl->id &&
510 tmp_ovl->manager == ovl->manager &&
511 tmp_ovl->info.enabled == true &&
512 tmp_ovl->info.zorder == info->zorder) {
513 DSSERR("%s and %s have same zorder: %d\n",
514 ovl->name, tmp_ovl->name, info->zorder);
515 return -EINVAL;
516 }
517 }
518 }
519
520 return 0;
521}
522
523static int dss_ovl_set_overlay_info(struct omap_overlay *ovl,
524 struct omap_overlay_info *info)
525{
526 int r;
527 struct omap_overlay_info old_info;
528
529 old_info = ovl->info;
530 ovl->info = *info;
531
532 if (ovl->manager) {
533 r = dss_check_overlay(ovl, ovl->manager->device);
534 if (r) {
535 ovl->info = old_info;
536 return r;
537 }
538 }
539
540 ovl->info_dirty = true;
541
542 return 0;
543}
544
545static void dss_ovl_get_overlay_info(struct omap_overlay *ovl,
546 struct omap_overlay_info *info)
547{
548 *info = ovl->info;
549}
550
551static int dss_ovl_wait_for_go(struct omap_overlay *ovl)
552{
553 return dss_mgr_wait_for_go_ovl(ovl);
554}
555
556static int omap_dss_set_manager(struct omap_overlay *ovl,
557 struct omap_overlay_manager *mgr)
558{
559 if (!mgr)
560 return -EINVAL;
561
562 if (ovl->manager) {
563 DSSERR("overlay '%s' already has a manager '%s'\n",
564 ovl->name, ovl->manager->name);
565 return -EINVAL;
566 }
567
568 if (ovl->info.enabled) {
569 DSSERR("overlay has to be disabled to change the manager\n");
570 return -EINVAL;
571 }
572
573 ovl->manager = mgr;
574 ovl->manager_changed = true;
575
576 /* XXX: When there is an overlay on a DSI manual update display, and
577 * the overlay is first disabled, then moved to tv, and enabled, we
578 * seem to get SYNC_LOST_DIGIT error.
579 *
580 * Waiting doesn't seem to help, but updating the manual update display
581 * after disabling the overlay seems to fix this. This hints that the
582 * overlay is perhaps somehow tied to the LCD output until the output
583 * is updated.
584 *
585 * Userspace workaround for this is to update the LCD after disabling
586 * the overlay, but before moving the overlay to TV.
587 */
588
589 return 0;
590}
591
592static int omap_dss_unset_manager(struct omap_overlay *ovl)
593{
594 if (!ovl->manager) {
595 DSSERR("failed to detach overlay: manager not set\n");
596 return -EINVAL;
597 }
598
599 if (ovl->info.enabled) {
600 DSSERR("overlay has to be disabled to unset the manager\n");
601 return -EINVAL;
602 }
603
604 ovl->manager = NULL;
605 ovl->manager_changed = true;
606
607 return 0;
608}
609
610int omap_dss_get_num_overlays(void) 454int omap_dss_get_num_overlays(void)
611{ 455{
612 return num_overlays; 456 return num_overlays;
@@ -615,134 +459,65 @@ EXPORT_SYMBOL(omap_dss_get_num_overlays);
615 459
616struct omap_overlay *omap_dss_get_overlay(int num) 460struct omap_overlay *omap_dss_get_overlay(int num)
617{ 461{
618 int i = 0; 462 if (num >= num_overlays)
619 struct omap_overlay *ovl; 463 return NULL;
620 464
621 list_for_each_entry(ovl, &overlay_list, list) { 465 return &overlays[num];
622 if (i++ == num)
623 return ovl;
624 }
625
626 return NULL;
627} 466}
628EXPORT_SYMBOL(omap_dss_get_overlay); 467EXPORT_SYMBOL(omap_dss_get_overlay);
629 468
630static void omap_dss_add_overlay(struct omap_overlay *overlay)
631{
632 ++num_overlays;
633 list_add_tail(&overlay->list, &overlay_list);
634}
635
636static struct omap_overlay *dispc_overlays[MAX_DSS_OVERLAYS];
637
638void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr)
639{
640 mgr->num_overlays = dss_feat_get_num_ovls();
641 mgr->overlays = dispc_overlays;
642}
643
644#ifdef L4_EXAMPLE
645static struct omap_overlay *l4_overlays[1];
646void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr)
647{
648 mgr->num_overlays = 1;
649 mgr->overlays = l4_overlays;
650}
651#endif
652
653void dss_init_overlays(struct platform_device *pdev) 469void dss_init_overlays(struct platform_device *pdev)
654{ 470{
655 int i, r; 471 int i, r;
656 472
657 INIT_LIST_HEAD(&overlay_list); 473 num_overlays = dss_feat_get_num_ovls();
658 474
659 num_overlays = 0; 475 overlays = kzalloc(sizeof(struct omap_overlay) * num_overlays,
476 GFP_KERNEL);
660 477
661 for (i = 0; i < dss_feat_get_num_ovls(); ++i) { 478 BUG_ON(overlays == NULL);
662 struct omap_overlay *ovl;
663 ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
664 479
665 BUG_ON(ovl == NULL); 480 for (i = 0; i < num_overlays; ++i) {
481 struct omap_overlay *ovl = &overlays[i];
666 482
667 switch (i) { 483 switch (i) {
668 case 0: 484 case 0:
669 ovl->name = "gfx"; 485 ovl->name = "gfx";
670 ovl->id = OMAP_DSS_GFX; 486 ovl->id = OMAP_DSS_GFX;
671 ovl->info.global_alpha = 255;
672 ovl->info.zorder = 0;
673 break; 487 break;
674 case 1: 488 case 1:
675 ovl->name = "vid1"; 489 ovl->name = "vid1";
676 ovl->id = OMAP_DSS_VIDEO1; 490 ovl->id = OMAP_DSS_VIDEO1;
677 ovl->info.global_alpha = 255;
678 ovl->info.zorder =
679 dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0;
680 break; 491 break;
681 case 2: 492 case 2:
682 ovl->name = "vid2"; 493 ovl->name = "vid2";
683 ovl->id = OMAP_DSS_VIDEO2; 494 ovl->id = OMAP_DSS_VIDEO2;
684 ovl->info.global_alpha = 255;
685 ovl->info.zorder =
686 dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0;
687 break; 495 break;
688 case 3: 496 case 3:
689 ovl->name = "vid3"; 497 ovl->name = "vid3";
690 ovl->id = OMAP_DSS_VIDEO3; 498 ovl->id = OMAP_DSS_VIDEO3;
691 ovl->info.global_alpha = 255;
692 ovl->info.zorder =
693 dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0;
694 break; 499 break;
695 } 500 }
696 501
697 ovl->set_manager = &omap_dss_set_manager; 502 ovl->is_enabled = &dss_ovl_is_enabled;
698 ovl->unset_manager = &omap_dss_unset_manager; 503 ovl->enable = &dss_ovl_enable;
699 ovl->set_overlay_info = &dss_ovl_set_overlay_info; 504 ovl->disable = &dss_ovl_disable;
700 ovl->get_overlay_info = &dss_ovl_get_overlay_info; 505 ovl->set_manager = &dss_ovl_set_manager;
701 ovl->wait_for_go = &dss_ovl_wait_for_go; 506 ovl->unset_manager = &dss_ovl_unset_manager;
507 ovl->set_overlay_info = &dss_ovl_set_info;
508 ovl->get_overlay_info = &dss_ovl_get_info;
509 ovl->wait_for_go = &dss_mgr_wait_for_go_ovl;
702 510
703 ovl->caps = dss_feat_get_overlay_caps(ovl->id); 511 ovl->caps = dss_feat_get_overlay_caps(ovl->id);
704 ovl->supported_modes = 512 ovl->supported_modes =
705 dss_feat_get_supported_color_modes(ovl->id); 513 dss_feat_get_supported_color_modes(ovl->id);
706 514
707 omap_dss_add_overlay(ovl);
708
709 r = kobject_init_and_add(&ovl->kobj, &overlay_ktype, 515 r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
710 &pdev->dev.kobj, "overlay%d", i); 516 &pdev->dev.kobj, "overlay%d", i);
711 517
712 if (r) {
713 DSSERR("failed to create sysfs file\n");
714 continue;
715 }
716
717 dispc_overlays[i] = ovl;
718 }
719
720#ifdef L4_EXAMPLE
721 {
722 struct omap_overlay *ovl;
723 ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
724
725 BUG_ON(ovl == NULL);
726
727 ovl->name = "l4";
728 ovl->supported_modes = OMAP_DSS_COLOR_RGB24U;
729
730 ovl->set_manager = &omap_dss_set_manager;
731 ovl->unset_manager = &omap_dss_unset_manager;
732 ovl->set_overlay_info = &dss_ovl_set_overlay_info;
733 ovl->get_overlay_info = &dss_ovl_get_overlay_info;
734
735 omap_dss_add_overlay(ovl);
736
737 r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
738 &pdev->dev.kobj, "overlayl4");
739
740 if (r) 518 if (r)
741 DSSERR("failed to create sysfs file\n"); 519 DSSERR("failed to create sysfs file\n");
742
743 l4_overlays[0] = ovl;
744 } 520 }
745#endif
746} 521}
747 522
748/* connect overlays to the new device, if not already connected. if force 523/* connect overlays to the new device, if not already connected. if force
@@ -795,8 +570,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
795 ovl = omap_dss_get_overlay(i); 570 ovl = omap_dss_get_overlay(i);
796 if (!ovl->manager || force) { 571 if (!ovl->manager || force) {
797 if (ovl->manager) 572 if (ovl->manager)
798 omap_dss_unset_manager(ovl); 573 ovl->unset_manager(ovl);
799 omap_dss_set_manager(ovl, mgr); 574 ovl->set_manager(ovl, mgr);
800 } 575 }
801 } 576 }
802 577
@@ -806,17 +581,95 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
806 581
807void dss_uninit_overlays(struct platform_device *pdev) 582void dss_uninit_overlays(struct platform_device *pdev)
808{ 583{
809 struct omap_overlay *ovl; 584 int i;
585
586 for (i = 0; i < num_overlays; ++i) {
587 struct omap_overlay *ovl = &overlays[i];
810 588
811 while (!list_empty(&overlay_list)) {
812 ovl = list_first_entry(&overlay_list,
813 struct omap_overlay, list);
814 list_del(&ovl->list);
815 kobject_del(&ovl->kobj); 589 kobject_del(&ovl->kobj);
816 kobject_put(&ovl->kobj); 590 kobject_put(&ovl->kobj);
817 kfree(ovl);
818 } 591 }
819 592
593 kfree(overlays);
594 overlays = NULL;
820 num_overlays = 0; 595 num_overlays = 0;
821} 596}
822 597
598int dss_ovl_simple_check(struct omap_overlay *ovl,
599 const struct omap_overlay_info *info)
600{
601 if (info->paddr == 0) {
602 DSSERR("check_overlay: paddr cannot be 0\n");
603 return -EINVAL;
604 }
605
606 if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
607 if (info->out_width != 0 && info->width != info->out_width) {
608 DSSERR("check_overlay: overlay %d doesn't support "
609 "scaling\n", ovl->id);
610 return -EINVAL;
611 }
612
613 if (info->out_height != 0 && info->height != info->out_height) {
614 DSSERR("check_overlay: overlay %d doesn't support "
615 "scaling\n", ovl->id);
616 return -EINVAL;
617 }
618 }
619
620 if ((ovl->supported_modes & info->color_mode) == 0) {
621 DSSERR("check_overlay: overlay %d doesn't support mode %d\n",
622 ovl->id, info->color_mode);
623 return -EINVAL;
624 }
625
626 if (info->zorder >= omap_dss_get_num_overlays()) {
627 DSSERR("check_overlay: zorder %d too high\n", info->zorder);
628 return -EINVAL;
629 }
630
631 return 0;
632}
633
634int dss_ovl_check(struct omap_overlay *ovl,
635 struct omap_overlay_info *info, struct omap_dss_device *dssdev)
636{
637 u16 outw, outh;
638 u16 dw, dh;
639
640 if (dssdev == NULL)
641 return 0;
642
643 dssdev->driver->get_resolution(dssdev, &dw, &dh);
644
645 if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
646 outw = info->width;
647 outh = info->height;
648 } else {
649 if (info->out_width == 0)
650 outw = info->width;
651 else
652 outw = info->out_width;
653
654 if (info->out_height == 0)
655 outh = info->height;
656 else
657 outh = info->out_height;
658 }
659
660 if (dw < info->pos_x + outw) {
661 DSSERR("overlay %d horizontally not inside the display area "
662 "(%d + %d >= %d)\n",
663 ovl->id, info->pos_x, outw, dw);
664 return -EINVAL;
665 }
666
667 if (dh < info->pos_y + outh) {
668 DSSERR("overlay %d vertically not inside the display area "
669 "(%d + %d >= %d)\n",
670 ovl->id, info->pos_y, outh, dh);
671 return -EINVAL;
672 }
673
674 return 0;
675}
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c
index 1130c608a561..814bb9500dca 100644
--- a/drivers/video/omap2/dss/rfbi.c
+++ b/drivers/video/omap2/dss/rfbi.c
@@ -784,7 +784,6 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
784 if (*w == 0 || *h == 0) 784 if (*w == 0 || *h == 0)
785 return -EINVAL; 785 return -EINVAL;
786 786
787 dss_setup_partial_planes(dssdev, x, y, w, h, true);
788 dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h); 787 dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h);
789 788
790 return 0; 789 return 0;
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c
index 40305ad7841e..8266ca0d666b 100644
--- a/drivers/video/omap2/dss/sdi.c
+++ b/drivers/video/omap2/dss/sdi.c
@@ -123,10 +123,14 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
123 goto err_sdi_enable; 123 goto err_sdi_enable;
124 mdelay(2); 124 mdelay(2);
125 125
126 dssdev->manager->enable(dssdev->manager); 126 r = dss_mgr_enable(dssdev->manager);
127 if (r)
128 goto err_mgr_enable;
127 129
128 return 0; 130 return 0;
129 131
132err_mgr_enable:
133 dss_sdi_disable();
130err_sdi_enable: 134err_sdi_enable:
131err_set_dispc_clock_div: 135err_set_dispc_clock_div:
132err_set_dss_clock_div: 136err_set_dss_clock_div:
@@ -145,7 +149,7 @@ EXPORT_SYMBOL(omapdss_sdi_display_enable);
145 149
146void omapdss_sdi_display_disable(struct omap_dss_device *dssdev) 150void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
147{ 151{
148 dssdev->manager->disable(dssdev->manager); 152 dss_mgr_disable(dssdev->manager);
149 153
150 dss_sdi_disable(); 154 dss_sdi_disable();
151 155
diff --git a/drivers/video/omap2/dss/ti_hdmi.h b/drivers/video/omap2/dss/ti_hdmi.h
index 2c3443dabb14..7503f7f619a7 100644
--- a/drivers/video/omap2/dss/ti_hdmi.h
+++ b/drivers/video/omap2/dss/ti_hdmi.h
@@ -110,6 +110,11 @@ struct ti_hdmi_ip_ops {
110 110
111 void (*dump_phy)(struct hdmi_ip_data *ip_data, struct seq_file *s); 111 void (*dump_phy)(struct hdmi_ip_data *ip_data, struct seq_file *s);
112 112
113#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
114 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
115 void (*audio_enable)(struct hdmi_ip_data *ip_data, bool start);
116#endif
117
113}; 118};
114 119
115struct hdmi_ip_data { 120struct hdmi_ip_data {
@@ -134,5 +139,8 @@ void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
134void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); 139void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
135void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); 140void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
136void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); 141void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
137 142#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
143 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
144void ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data, bool enable);
145#endif
138#endif 146#endif
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
index e1a6ce518af6..9af81f18f163 100644
--- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
+++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
@@ -1204,36 +1204,13 @@ int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data,
1204 return 0; 1204 return 0;
1205} 1205}
1206 1206
1207int hdmi_audio_trigger(struct hdmi_ip_data *ip_data, 1207void ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data, bool enable)
1208 struct snd_pcm_substream *substream, int cmd,
1209 struct snd_soc_dai *dai)
1210{ 1208{
1211 int err = 0; 1209 REG_FLD_MOD(hdmi_av_base(ip_data),
1212 switch (cmd) { 1210 HDMI_CORE_AV_AUD_MODE, enable, 0, 0);
1213 case SNDRV_PCM_TRIGGER_START: 1211 REG_FLD_MOD(hdmi_wp_base(ip_data),
1214 case SNDRV_PCM_TRIGGER_RESUME: 1212 HDMI_WP_AUDIO_CTRL, enable, 31, 31);
1215 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 1213 REG_FLD_MOD(hdmi_wp_base(ip_data),
1216 REG_FLD_MOD(hdmi_av_base(ip_data), 1214 HDMI_WP_AUDIO_CTRL, enable, 30, 30);
1217 HDMI_CORE_AV_AUD_MODE, 1, 0, 0);
1218 REG_FLD_MOD(hdmi_wp_base(ip_data),
1219 HDMI_WP_AUDIO_CTRL, 1, 31, 31);
1220 REG_FLD_MOD(hdmi_wp_base(ip_data),
1221 HDMI_WP_AUDIO_CTRL, 1, 30, 30);
1222 break;
1223
1224 case SNDRV_PCM_TRIGGER_STOP:
1225 case SNDRV_PCM_TRIGGER_SUSPEND:
1226 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1227 REG_FLD_MOD(hdmi_av_base(ip_data),
1228 HDMI_CORE_AV_AUD_MODE, 0, 0, 0);
1229 REG_FLD_MOD(hdmi_wp_base(ip_data),
1230 HDMI_WP_AUDIO_CTRL, 0, 30, 30);
1231 REG_FLD_MOD(hdmi_wp_base(ip_data),
1232 HDMI_WP_AUDIO_CTRL, 0, 31, 31);
1233 break;
1234 default:
1235 err = -EINVAL;
1236 }
1237 return err;
1238} 1215}
1239#endif 1216#endif
diff --git a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
index 204095632d27..a442998980f1 100644
--- a/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
+++ b/drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
@@ -576,9 +576,6 @@ struct hdmi_core_audio_config {
576 576
577#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ 577#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
578 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) 578 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
579int hdmi_audio_trigger(struct hdmi_ip_data *ip_data,
580 struct snd_pcm_substream *substream, int cmd,
581 struct snd_soc_dai *dai);
582int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data, 579int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data,
583 u32 sample_freq, u32 *n, u32 *cts); 580 u32 sample_freq, u32 *n, u32 *cts);
584void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data, 581void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index 7533458ba4d2..b3e9f9091581 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -417,9 +417,10 @@ static const struct venc_config *venc_timings_to_config(
417 BUG(); 417 BUG();
418} 418}
419 419
420static void venc_power_on(struct omap_dss_device *dssdev) 420static int venc_power_on(struct omap_dss_device *dssdev)
421{ 421{
422 u32 l; 422 u32 l;
423 int r;
423 424
424 venc_reset(); 425 venc_reset();
425 venc_write_config(venc_timings_to_config(&dssdev->panel.timings)); 426 venc_write_config(venc_timings_to_config(&dssdev->panel.timings));
@@ -447,7 +448,22 @@ static void venc_power_on(struct omap_dss_device *dssdev)
447 if (dssdev->platform_enable) 448 if (dssdev->platform_enable)
448 dssdev->platform_enable(dssdev); 449 dssdev->platform_enable(dssdev);
449 450
450 dssdev->manager->enable(dssdev->manager); 451 r = dss_mgr_enable(dssdev->manager);
452 if (r)
453 goto err;
454
455 return 0;
456
457err:
458 venc_write_reg(VENC_OUTPUT_CONTROL, 0);
459 dss_set_dac_pwrdn_bgz(0);
460
461 if (dssdev->platform_disable)
462 dssdev->platform_disable(dssdev);
463
464 regulator_disable(venc.vdda_dac_reg);
465
466 return r;
451} 467}
452 468
453static void venc_power_off(struct omap_dss_device *dssdev) 469static void venc_power_off(struct omap_dss_device *dssdev)
@@ -455,7 +471,7 @@ static void venc_power_off(struct omap_dss_device *dssdev)
455 venc_write_reg(VENC_OUTPUT_CONTROL, 0); 471 venc_write_reg(VENC_OUTPUT_CONTROL, 0);
456 dss_set_dac_pwrdn_bgz(0); 472 dss_set_dac_pwrdn_bgz(0);
457 473
458 dssdev->manager->disable(dssdev->manager); 474 dss_mgr_disable(dssdev->manager);
459 475
460 if (dssdev->platform_disable) 476 if (dssdev->platform_disable)
461 dssdev->platform_disable(dssdev); 477 dssdev->platform_disable(dssdev);
@@ -504,7 +520,9 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
504 if (r) 520 if (r)
505 goto err1; 521 goto err1;
506 522
507 venc_power_on(dssdev); 523 r = venc_power_on(dssdev);
524 if (r)
525 goto err2;
508 526
509 venc.wss_data = 0; 527 venc.wss_data = 0;
510 528
@@ -512,6 +530,8 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
512 530
513 mutex_unlock(&venc.venc_lock); 531 mutex_unlock(&venc.venc_lock);
514 return 0; 532 return 0;
533err2:
534 venc_runtime_put();
515err1: 535err1:
516 omap_dss_stop_device(dssdev); 536 omap_dss_stop_device(dssdev);
517err0: 537err0:
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index df7bcce5b107..16ba6196f330 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -111,28 +111,22 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
111 set_fb_fix(fbi); 111 set_fb_fix(fbi);
112 } 112 }
113 113
114 if (pi->enabled) { 114 if (!pi->enabled) {
115 struct omap_overlay_info info; 115 r = ovl->disable(ovl);
116 if (r)
117 goto undo;
118 }
116 119
120 if (pi->enabled) {
117 r = omapfb_setup_overlay(fbi, ovl, pi->pos_x, pi->pos_y, 121 r = omapfb_setup_overlay(fbi, ovl, pi->pos_x, pi->pos_y,
118 pi->out_width, pi->out_height); 122 pi->out_width, pi->out_height);
119 if (r) 123 if (r)
120 goto undo; 124 goto undo;
121
122 ovl->get_overlay_info(ovl, &info);
123
124 if (!info.enabled) {
125 info.enabled = pi->enabled;
126 r = ovl->set_overlay_info(ovl, &info);
127 if (r)
128 goto undo;
129 }
130 } else { 125 } else {
131 struct omap_overlay_info info; 126 struct omap_overlay_info info;
132 127
133 ovl->get_overlay_info(ovl, &info); 128 ovl->get_overlay_info(ovl, &info);
134 129
135 info.enabled = pi->enabled;
136 info.pos_x = pi->pos_x; 130 info.pos_x = pi->pos_x;
137 info.pos_y = pi->pos_y; 131 info.pos_y = pi->pos_y;
138 info.out_width = pi->out_width; 132 info.out_width = pi->out_width;
@@ -146,6 +140,12 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
146 if (ovl->manager) 140 if (ovl->manager)
147 ovl->manager->apply(ovl->manager); 141 ovl->manager->apply(ovl->manager);
148 142
143 if (pi->enabled) {
144 r = ovl->enable(ovl);
145 if (r)
146 goto undo;
147 }
148
149 /* Release the locks in a specific order to keep lockdep happy */ 149 /* Release the locks in a specific order to keep lockdep happy */
150 if (old_rg->id > new_rg->id) { 150 if (old_rg->id > new_rg->id) {
151 omapfb_put_mem_region(old_rg); 151 omapfb_put_mem_region(old_rg);
@@ -189,19 +189,19 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
189 memset(pi, 0, sizeof(*pi)); 189 memset(pi, 0, sizeof(*pi));
190 } else { 190 } else {
191 struct omap_overlay *ovl; 191 struct omap_overlay *ovl;
192 struct omap_overlay_info *ovli; 192 struct omap_overlay_info ovli;
193 193
194 ovl = ofbi->overlays[0]; 194 ovl = ofbi->overlays[0];
195 ovli = &ovl->info; 195 ovl->get_overlay_info(ovl, &ovli);
196 196
197 pi->pos_x = ovli->pos_x; 197 pi->pos_x = ovli.pos_x;
198 pi->pos_y = ovli->pos_y; 198 pi->pos_y = ovli.pos_y;
199 pi->enabled = ovli->enabled; 199 pi->enabled = ovl->is_enabled(ovl);
200 pi->channel_out = 0; /* xxx */ 200 pi->channel_out = 0; /* xxx */
201 pi->mirror = 0; 201 pi->mirror = 0;
202 pi->mem_idx = get_mem_idx(ofbi); 202 pi->mem_idx = get_mem_idx(ofbi);
203 pi->out_width = ovli->out_width; 203 pi->out_width = ovli.out_width;
204 pi->out_height = ovli->out_height; 204 pi->out_height = ovli.out_height;
205 } 205 }
206 206
207 return 0; 207 return 0;
@@ -238,7 +238,9 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
238 continue; 238 continue;
239 239
240 for (j = 0; j < ofbi2->num_overlays; j++) { 240 for (j = 0; j < ofbi2->num_overlays; j++) {
241 if (ofbi2->overlays[j]->info.enabled) { 241 struct omap_overlay *ovl;
242 ovl = ofbi2->overlays[j];
243 if (ovl->is_enabled(ovl)) {
242 r = -EBUSY; 244 r = -EBUSY;
243 goto out; 245 goto out;
244 } 246 }
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 68ba1f800082..ce158311ff59 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -970,16 +970,20 @@ int omapfb_apply_changes(struct fb_info *fbi, int init)
970 outh = var->yres; 970 outh = var->yres;
971 } 971 }
972 } else { 972 } else {
973 outw = ovl->info.out_width; 973 struct omap_overlay_info info;
974 outh = ovl->info.out_height; 974 ovl->get_overlay_info(ovl, &info);
975 outw = info.out_width;
976 outh = info.out_height;
975 } 977 }
976 978
977 if (init) { 979 if (init) {
978 posx = 0; 980 posx = 0;
979 posy = 0; 981 posy = 0;
980 } else { 982 } else {
981 posx = ovl->info.pos_x; 983 struct omap_overlay_info info;
982 posy = ovl->info.pos_y; 984 ovl->get_overlay_info(ovl, &info);
985 posx = info.pos_x;
986 posy = info.pos_y;
983 } 987 }
984 988
985 r = omapfb_setup_overlay(fbi, ovl, posx, posy, outw, outh); 989 r = omapfb_setup_overlay(fbi, ovl, posx, posy, outw, outh);
@@ -2067,6 +2071,8 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
2067 if (ofbi->num_overlays > 0) { 2071 if (ofbi->num_overlays > 0) {
2068 struct omap_overlay *ovl = ofbi->overlays[0]; 2072 struct omap_overlay *ovl = ofbi->overlays[0];
2069 2073
2074 ovl->manager->apply(ovl->manager);
2075
2070 r = omapfb_overlay_enable(ovl, 1); 2076 r = omapfb_overlay_enable(ovl, 1);
2071 2077
2072 if (r) { 2078 if (r) {
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
index 1694d5148f32..e8d8cc76a435 100644
--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
+++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
@@ -473,7 +473,9 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
473 continue; 473 continue;
474 474
475 for (j = 0; j < ofbi2->num_overlays; j++) { 475 for (j = 0; j < ofbi2->num_overlays; j++) {
476 if (ofbi2->overlays[j]->info.enabled) { 476 struct omap_overlay *ovl;
477 ovl = ofbi2->overlays[j];
478 if (ovl->is_enabled(ovl)) {
477 r = -EBUSY; 479 r = -EBUSY;
478 goto out; 480 goto out;
479 } 481 }
diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/omap2/omapfb/omapfb.h
index e12d384ea520..c0bdc9b54ecf 100644
--- a/drivers/video/omap2/omapfb/omapfb.h
+++ b/drivers/video/omap2/omapfb/omapfb.h
@@ -181,13 +181,10 @@ static inline void omapfb_unlock(struct omapfb2_device *fbdev)
181static inline int omapfb_overlay_enable(struct omap_overlay *ovl, 181static inline int omapfb_overlay_enable(struct omap_overlay *ovl,
182 int enable) 182 int enable)
183{ 183{
184 struct omap_overlay_info info; 184 if (enable)
185 185 return ovl->enable(ovl);
186 ovl->get_overlay_info(ovl, &info); 186 else
187 if (info.enabled == enable) 187 return ovl->disable(ovl);
188 return 0;
189 info.enabled = enable;
190 return ovl->set_overlay_info(ovl, &info);
191} 188}
192 189
193static inline struct omapfb2_mem_region * 190static inline struct omapfb2_mem_region *
diff --git a/drivers/video/pnx4008/pnxrgbfb.c b/drivers/video/pnx4008/pnxrgbfb.c
index b2252fea2858..6d30428e9cf9 100644
--- a/drivers/video/pnx4008/pnxrgbfb.c
+++ b/drivers/video/pnx4008/pnxrgbfb.c
@@ -193,17 +193,6 @@ static struct platform_driver rgbfb_driver = {
193 .remove = rgbfb_remove, 193 .remove = rgbfb_remove,
194}; 194};
195 195
196static int __init rgbfb_init(void) 196module_platform_driver(rgbfb_driver);
197{
198 return platform_driver_register(&rgbfb_driver);
199}
200
201static void __exit rgbfb_exit(void)
202{
203 platform_driver_unregister(&rgbfb_driver);
204}
205
206module_init(rgbfb_init);
207module_exit(rgbfb_exit);
208 197
209MODULE_LICENSE("GPL"); 198MODULE_LICENSE("GPL");
diff --git a/drivers/video/pnx4008/sdum.c b/drivers/video/pnx4008/sdum.c
index 50e00395240f..c5c741452cac 100644
--- a/drivers/video/pnx4008/sdum.c
+++ b/drivers/video/pnx4008/sdum.c
@@ -856,17 +856,6 @@ static struct platform_driver sdum_driver = {
856 .resume = sdum_resume, 856 .resume = sdum_resume,
857}; 857};
858 858
859int __init sdum_init(void) 859module_platform_driver(sdum_driver);
860{
861 return platform_driver_register(&sdum_driver);
862}
863
864static void __exit sdum_exit(void)
865{
866 platform_driver_unregister(&sdum_driver);
867};
868
869module_init(sdum_init);
870module_exit(sdum_exit);
871 860
872MODULE_LICENSE("GPL"); 861MODULE_LICENSE("GPL");
diff --git a/drivers/video/pxa168fb.c b/drivers/video/pxa168fb.c
index 18ead6f0184d..8384b941f6ba 100644
--- a/drivers/video/pxa168fb.c
+++ b/drivers/video/pxa168fb.c
@@ -832,17 +832,7 @@ static struct platform_driver pxa168fb_driver = {
832 .remove = __devexit_p(pxa168fb_remove), 832 .remove = __devexit_p(pxa168fb_remove),
833}; 833};
834 834
835static int __init pxa168fb_init(void) 835module_platform_driver(pxa168fb_driver);
836{
837 return platform_driver_register(&pxa168fb_driver);
838}
839module_init(pxa168fb_init);
840
841static void __exit pxa168fb_exit(void)
842{
843 platform_driver_unregister(&pxa168fb_driver);
844}
845module_exit(pxa168fb_exit);
846 836
847MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com> " 837MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com> "
848 "Green Wan <gwan@marvell.com>"); 838 "Green Wan <gwan@marvell.com>");
diff --git a/drivers/video/pxa3xx-gcu.c b/drivers/video/pxa3xx-gcu.c
index 1ed8b366618d..1d71c08a818f 100644
--- a/drivers/video/pxa3xx-gcu.c
+++ b/drivers/video/pxa3xx-gcu.c
@@ -747,20 +747,7 @@ static struct platform_driver pxa3xx_gcu_driver = {
747 }, 747 },
748}; 748};
749 749
750static int __init 750module_platform_driver(pxa3xx_gcu_driver);
751pxa3xx_gcu_init(void)
752{
753 return platform_driver_register(&pxa3xx_gcu_driver);
754}
755
756static void __exit
757pxa3xx_gcu_exit(void)
758{
759 platform_driver_unregister(&pxa3xx_gcu_driver);
760}
761
762module_init(pxa3xx_gcu_init);
763module_exit(pxa3xx_gcu_exit);
764 751
765MODULE_DESCRIPTION("PXA3xx graphics controller unit driver"); 752MODULE_DESCRIPTION("PXA3xx graphics controller unit driver");
766MODULE_LICENSE("GPL"); 753MODULE_LICENSE("GPL");
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 0753b1cfcb8b..0c63b69b6340 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -192,6 +192,7 @@ struct s3c_fb_vsync {
192 * @regs: The mapped hardware registers. 192 * @regs: The mapped hardware registers.
193 * @variant: Variant information for this hardware. 193 * @variant: Variant information for this hardware.
194 * @enabled: A bitmask of enabled hardware windows. 194 * @enabled: A bitmask of enabled hardware windows.
195 * @output_on: Flag if the physical output is enabled.
195 * @pdata: The platform configuration data passed with the device. 196 * @pdata: The platform configuration data passed with the device.
196 * @windows: The hardware windows that have been claimed. 197 * @windows: The hardware windows that have been claimed.
197 * @irq_no: IRQ line number 198 * @irq_no: IRQ line number
@@ -208,6 +209,7 @@ struct s3c_fb {
208 struct s3c_fb_variant variant; 209 struct s3c_fb_variant variant;
209 210
210 unsigned char enabled; 211 unsigned char enabled;
212 bool output_on;
211 213
212 struct s3c_fb_platdata *pdata; 214 struct s3c_fb_platdata *pdata;
213 struct s3c_fb_win *windows[S3C_FB_MAX_WIN]; 215 struct s3c_fb_win *windows[S3C_FB_MAX_WIN];
@@ -441,6 +443,39 @@ static void shadow_protect_win(struct s3c_fb_win *win, bool protect)
441} 443}
442 444
443/** 445/**
446 * s3c_fb_enable() - Set the state of the main LCD output
447 * @sfb: The main framebuffer state.
448 * @enable: The state to set.
449 */
450static void s3c_fb_enable(struct s3c_fb *sfb, int enable)
451{
452 u32 vidcon0 = readl(sfb->regs + VIDCON0);
453
454 if (enable && !sfb->output_on)
455 pm_runtime_get_sync(sfb->dev);
456
457 if (enable) {
458 vidcon0 |= VIDCON0_ENVID | VIDCON0_ENVID_F;
459 } else {
460 /* see the note in the framebuffer datasheet about
461 * why you cannot take both of these bits down at the
462 * same time. */
463
464 if (vidcon0 & VIDCON0_ENVID) {
465 vidcon0 |= VIDCON0_ENVID;
466 vidcon0 &= ~VIDCON0_ENVID_F;
467 }
468 }
469
470 writel(vidcon0, sfb->regs + VIDCON0);
471
472 if (!enable && sfb->output_on)
473 pm_runtime_put_sync(sfb->dev);
474
475 sfb->output_on = enable;
476}
477
478/**
444 * s3c_fb_set_par() - framebuffer request to set new framebuffer state. 479 * s3c_fb_set_par() - framebuffer request to set new framebuffer state.
445 * @info: The framebuffer to change. 480 * @info: The framebuffer to change.
446 * 481 *
@@ -461,6 +496,8 @@ static int s3c_fb_set_par(struct fb_info *info)
461 496
462 dev_dbg(sfb->dev, "setting framebuffer parameters\n"); 497 dev_dbg(sfb->dev, "setting framebuffer parameters\n");
463 498
499 pm_runtime_get_sync(sfb->dev);
500
464 shadow_protect_win(win, 1); 501 shadow_protect_win(win, 1);
465 502
466 switch (var->bits_per_pixel) { 503 switch (var->bits_per_pixel) {
@@ -510,9 +547,10 @@ static int s3c_fb_set_par(struct fb_info *info)
510 if (sfb->variant.is_2443) 547 if (sfb->variant.is_2443)
511 data |= (1 << 5); 548 data |= (1 << 5);
512 549
513 data |= VIDCON0_ENVID | VIDCON0_ENVID_F;
514 writel(data, regs + VIDCON0); 550 writel(data, regs + VIDCON0);
515 551
552 s3c_fb_enable(sfb, 1);
553
516 data = VIDTCON0_VBPD(var->upper_margin - 1) | 554 data = VIDTCON0_VBPD(var->upper_margin - 1) |
517 VIDTCON0_VFPD(var->lower_margin - 1) | 555 VIDTCON0_VFPD(var->lower_margin - 1) |
518 VIDTCON0_VSPW(var->vsync_len - 1); 556 VIDTCON0_VSPW(var->vsync_len - 1);
@@ -574,6 +612,7 @@ static int s3c_fb_set_par(struct fb_info *info)
574 } 612 }
575 613
576 data = WINCONx_ENWIN; 614 data = WINCONx_ENWIN;
615 sfb->enabled |= (1 << win->index);
577 616
578 /* note, since we have to round up the bits-per-pixel, we end up 617 /* note, since we have to round up the bits-per-pixel, we end up
579 * relying on the bitfield information for r/g/b/a to work out 618 * relying on the bitfield information for r/g/b/a to work out
@@ -621,7 +660,8 @@ static int s3c_fb_set_par(struct fb_info *info)
621 } else if (var->transp.length == 1) 660 } else if (var->transp.length == 1)
622 data |= WINCON1_BPPMODE_25BPP_A1888 661 data |= WINCON1_BPPMODE_25BPP_A1888
623 | WINCON1_BLD_PIX; 662 | WINCON1_BLD_PIX;
624 else if (var->transp.length == 4) 663 else if ((var->transp.length == 4) ||
664 (var->transp.length == 8))
625 data |= WINCON1_BPPMODE_28BPP_A4888 665 data |= WINCON1_BPPMODE_28BPP_A4888
626 | WINCON1_BLD_PIX | WINCON1_ALPHA_SEL; 666 | WINCON1_BLD_PIX | WINCON1_ALPHA_SEL;
627 else 667 else
@@ -654,6 +694,8 @@ static int s3c_fb_set_par(struct fb_info *info)
654 694
655 shadow_protect_win(win, 0); 695 shadow_protect_win(win, 0);
656 696
697 pm_runtime_put_sync(sfb->dev);
698
657 return 0; 699 return 0;
658} 700}
659 701
@@ -725,6 +767,8 @@ static int s3c_fb_setcolreg(unsigned regno,
725 dev_dbg(sfb->dev, "%s: win %d: %d => rgb=%d/%d/%d\n", 767 dev_dbg(sfb->dev, "%s: win %d: %d => rgb=%d/%d/%d\n",
726 __func__, win->index, regno, red, green, blue); 768 __func__, win->index, regno, red, green, blue);
727 769
770 pm_runtime_get_sync(sfb->dev);
771
728 switch (info->fix.visual) { 772 switch (info->fix.visual) {
729 case FB_VISUAL_TRUECOLOR: 773 case FB_VISUAL_TRUECOLOR:
730 /* true-colour, use pseudo-palette */ 774 /* true-colour, use pseudo-palette */
@@ -752,39 +796,15 @@ static int s3c_fb_setcolreg(unsigned regno,
752 break; 796 break;
753 797
754 default: 798 default:
799 pm_runtime_put_sync(sfb->dev);
755 return 1; /* unknown type */ 800 return 1; /* unknown type */
756 } 801 }
757 802
803 pm_runtime_put_sync(sfb->dev);
758 return 0; 804 return 0;
759} 805}
760 806
761/** 807/**
762 * s3c_fb_enable() - Set the state of the main LCD output
763 * @sfb: The main framebuffer state.
764 * @enable: The state to set.
765 */
766static void s3c_fb_enable(struct s3c_fb *sfb, int enable)
767{
768 u32 vidcon0 = readl(sfb->regs + VIDCON0);
769
770 if (enable)
771 vidcon0 |= VIDCON0_ENVID | VIDCON0_ENVID_F;
772 else {
773 /* see the note in the framebuffer datasheet about
774 * why you cannot take both of these bits down at the
775 * same time. */
776
777 if (!(vidcon0 & VIDCON0_ENVID))
778 return;
779
780 vidcon0 |= VIDCON0_ENVID;
781 vidcon0 &= ~VIDCON0_ENVID_F;
782 }
783
784 writel(vidcon0, sfb->regs + VIDCON0);
785}
786
787/**
788 * s3c_fb_blank() - blank or unblank the given window 808 * s3c_fb_blank() - blank or unblank the given window
789 * @blank_mode: The blank state from FB_BLANK_* 809 * @blank_mode: The blank state from FB_BLANK_*
790 * @info: The framebuffer to blank. 810 * @info: The framebuffer to blank.
@@ -800,6 +820,8 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info)
800 820
801 dev_dbg(sfb->dev, "blank mode %d\n", blank_mode); 821 dev_dbg(sfb->dev, "blank mode %d\n", blank_mode);
802 822
823 pm_runtime_get_sync(sfb->dev);
824
803 wincon = readl(sfb->regs + sfb->variant.wincon + (index * 4)); 825 wincon = readl(sfb->regs + sfb->variant.wincon + (index * 4));
804 826
805 switch (blank_mode) { 827 switch (blank_mode) {
@@ -810,12 +832,16 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info)
810 832
811 case FB_BLANK_NORMAL: 833 case FB_BLANK_NORMAL:
812 /* disable the DMA and display 0x0 (black) */ 834 /* disable the DMA and display 0x0 (black) */
835 shadow_protect_win(win, 1);
813 writel(WINxMAP_MAP | WINxMAP_MAP_COLOUR(0x0), 836 writel(WINxMAP_MAP | WINxMAP_MAP_COLOUR(0x0),
814 sfb->regs + sfb->variant.winmap + (index * 4)); 837 sfb->regs + sfb->variant.winmap + (index * 4));
838 shadow_protect_win(win, 0);
815 break; 839 break;
816 840
817 case FB_BLANK_UNBLANK: 841 case FB_BLANK_UNBLANK:
842 shadow_protect_win(win, 1);
818 writel(0x0, sfb->regs + sfb->variant.winmap + (index * 4)); 843 writel(0x0, sfb->regs + sfb->variant.winmap + (index * 4));
844 shadow_protect_win(win, 0);
819 wincon |= WINCONx_ENWIN; 845 wincon |= WINCONx_ENWIN;
820 sfb->enabled |= (1 << index); 846 sfb->enabled |= (1 << index);
821 break; 847 break;
@@ -823,10 +849,13 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info)
823 case FB_BLANK_VSYNC_SUSPEND: 849 case FB_BLANK_VSYNC_SUSPEND:
824 case FB_BLANK_HSYNC_SUSPEND: 850 case FB_BLANK_HSYNC_SUSPEND:
825 default: 851 default:
852 pm_runtime_put_sync(sfb->dev);
826 return 1; 853 return 1;
827 } 854 }
828 855
856 shadow_protect_win(win, 1);
829 writel(wincon, sfb->regs + sfb->variant.wincon + (index * 4)); 857 writel(wincon, sfb->regs + sfb->variant.wincon + (index * 4));
858 shadow_protect_win(win, 0);
830 859
831 /* Check the enabled state to see if we need to be running the 860 /* Check the enabled state to see if we need to be running the
832 * main LCD interface, as if there are no active windows then 861 * main LCD interface, as if there are no active windows then
@@ -845,8 +874,13 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info)
845 /* we're stuck with this until we can do something about overriding 874 /* we're stuck with this until we can do something about overriding
846 * the power control using the blanking event for a single fb. 875 * the power control using the blanking event for a single fb.
847 */ 876 */
848 if (index == sfb->pdata->default_win) 877 if (index == sfb->pdata->default_win) {
878 shadow_protect_win(win, 1);
849 s3c_fb_enable(sfb, blank_mode != FB_BLANK_POWERDOWN ? 1 : 0); 879 s3c_fb_enable(sfb, blank_mode != FB_BLANK_POWERDOWN ? 1 : 0);
880 shadow_protect_win(win, 0);
881 }
882
883 pm_runtime_put_sync(sfb->dev);
850 884
851 return 0; 885 return 0;
852} 886}
@@ -870,6 +904,8 @@ static int s3c_fb_pan_display(struct fb_var_screeninfo *var,
870 void __iomem *buf = sfb->regs + win->index * 8; 904 void __iomem *buf = sfb->regs + win->index * 8;
871 unsigned int start_boff, end_boff; 905 unsigned int start_boff, end_boff;
872 906
907 pm_runtime_get_sync(sfb->dev);
908
873 /* Offset in bytes to the start of the displayed area */ 909 /* Offset in bytes to the start of the displayed area */
874 start_boff = var->yoffset * info->fix.line_length; 910 start_boff = var->yoffset * info->fix.line_length;
875 /* X offset depends on the current bpp */ 911 /* X offset depends on the current bpp */
@@ -888,6 +924,7 @@ static int s3c_fb_pan_display(struct fb_var_screeninfo *var,
888 break; 924 break;
889 default: 925 default:
890 dev_err(sfb->dev, "invalid bpp\n"); 926 dev_err(sfb->dev, "invalid bpp\n");
927 pm_runtime_put_sync(sfb->dev);
891 return -EINVAL; 928 return -EINVAL;
892 } 929 }
893 } 930 }
@@ -903,6 +940,7 @@ static int s3c_fb_pan_display(struct fb_var_screeninfo *var,
903 940
904 shadow_protect_win(win, 0); 941 shadow_protect_win(win, 0);
905 942
943 pm_runtime_put_sync(sfb->dev);
906 return 0; 944 return 0;
907} 945}
908 946
@@ -992,11 +1030,16 @@ static int s3c_fb_wait_for_vsync(struct s3c_fb *sfb, u32 crtc)
992 if (crtc != 0) 1030 if (crtc != 0)
993 return -ENODEV; 1031 return -ENODEV;
994 1032
1033 pm_runtime_get_sync(sfb->dev);
1034
995 count = sfb->vsync_info.count; 1035 count = sfb->vsync_info.count;
996 s3c_fb_enable_irq(sfb); 1036 s3c_fb_enable_irq(sfb);
997 ret = wait_event_interruptible_timeout(sfb->vsync_info.wait, 1037 ret = wait_event_interruptible_timeout(sfb->vsync_info.wait,
998 count != sfb->vsync_info.count, 1038 count != sfb->vsync_info.count,
999 msecs_to_jiffies(VSYNC_TIMEOUT_MSEC)); 1039 msecs_to_jiffies(VSYNC_TIMEOUT_MSEC));
1040
1041 pm_runtime_put_sync(sfb->dev);
1042
1000 if (ret == 0) 1043 if (ret == 0)
1001 return -ETIMEDOUT; 1044 return -ETIMEDOUT;
1002 1045
@@ -1027,30 +1070,8 @@ static int s3c_fb_ioctl(struct fb_info *info, unsigned int cmd,
1027 return ret; 1070 return ret;
1028} 1071}
1029 1072
1030static int s3c_fb_open(struct fb_info *info, int user)
1031{
1032 struct s3c_fb_win *win = info->par;
1033 struct s3c_fb *sfb = win->parent;
1034
1035 pm_runtime_get_sync(sfb->dev);
1036
1037 return 0;
1038}
1039
1040static int s3c_fb_release(struct fb_info *info, int user)
1041{
1042 struct s3c_fb_win *win = info->par;
1043 struct s3c_fb *sfb = win->parent;
1044
1045 pm_runtime_put_sync(sfb->dev);
1046
1047 return 0;
1048}
1049
1050static struct fb_ops s3c_fb_ops = { 1073static struct fb_ops s3c_fb_ops = {
1051 .owner = THIS_MODULE, 1074 .owner = THIS_MODULE,
1052 .fb_open = s3c_fb_open,
1053 .fb_release = s3c_fb_release,
1054 .fb_check_var = s3c_fb_check_var, 1075 .fb_check_var = s3c_fb_check_var,
1055 .fb_set_par = s3c_fb_set_par, 1076 .fb_set_par = s3c_fb_set_par,
1056 .fb_blank = s3c_fb_blank, 1077 .fb_blank = s3c_fb_blank,
@@ -1452,7 +1473,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
1452 dev_err(dev, "failed to create window %d\n", win); 1473 dev_err(dev, "failed to create window %d\n", win);
1453 for (; win >= 0; win--) 1474 for (; win >= 0; win--)
1454 s3c_fb_release_win(sfb, sfb->windows[win]); 1475 s3c_fb_release_win(sfb, sfb->windows[win]);
1455 goto err_irq; 1476 goto err_pm_runtime;
1456 } 1477 }
1457 } 1478 }
1458 1479
@@ -1461,7 +1482,8 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
1461 1482
1462 return 0; 1483 return 0;
1463 1484
1464err_irq: 1485err_pm_runtime:
1486 pm_runtime_put_sync(sfb->dev);
1465 free_irq(sfb->irq_no, sfb); 1487 free_irq(sfb->irq_no, sfb);
1466 1488
1467err_ioremap: 1489err_ioremap:
@@ -1471,6 +1493,8 @@ err_req_region:
1471 release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res)); 1493 release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res));
1472 1494
1473err_lcd_clk: 1495err_lcd_clk:
1496 pm_runtime_disable(sfb->dev);
1497
1474 if (!sfb->variant.has_clksel) { 1498 if (!sfb->variant.has_clksel) {
1475 clk_disable(sfb->lcd_clk); 1499 clk_disable(sfb->lcd_clk);
1476 clk_put(sfb->lcd_clk); 1500 clk_put(sfb->lcd_clk);
@@ -1524,7 +1548,7 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
1524 return 0; 1548 return 0;
1525} 1549}
1526 1550
1527#ifdef CONFIG_PM 1551#ifdef CONFIG_PM_SLEEP
1528static int s3c_fb_suspend(struct device *dev) 1552static int s3c_fb_suspend(struct device *dev)
1529{ 1553{
1530 struct platform_device *pdev = to_platform_device(dev); 1554 struct platform_device *pdev = to_platform_device(dev);
@@ -1571,10 +1595,15 @@ static int s3c_fb_resume(struct device *dev)
1571 1595
1572 for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) { 1596 for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) {
1573 void __iomem *regs = sfb->regs + sfb->variant.keycon; 1597 void __iomem *regs = sfb->regs + sfb->variant.keycon;
1598 win = sfb->windows[win_no];
1599 if (!win)
1600 continue;
1574 1601
1602 shadow_protect_win(win, 1);
1575 regs += (win_no * 8); 1603 regs += (win_no * 8);
1576 writel(0xffffff, regs + WKEYCON0); 1604 writel(0xffffff, regs + WKEYCON0);
1577 writel(0xffffff, regs + WKEYCON1); 1605 writel(0xffffff, regs + WKEYCON1);
1606 shadow_protect_win(win, 0);
1578 } 1607 }
1579 1608
1580 /* restore framebuffers */ 1609 /* restore framebuffers */
@@ -1589,27 +1618,19 @@ static int s3c_fb_resume(struct device *dev)
1589 1618
1590 return 0; 1619 return 0;
1591} 1620}
1621#endif
1592 1622
1623#ifdef CONFIG_PM_RUNTIME
1593static int s3c_fb_runtime_suspend(struct device *dev) 1624static int s3c_fb_runtime_suspend(struct device *dev)
1594{ 1625{
1595 struct platform_device *pdev = to_platform_device(dev); 1626 struct platform_device *pdev = to_platform_device(dev);
1596 struct s3c_fb *sfb = platform_get_drvdata(pdev); 1627 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1597 struct s3c_fb_win *win;
1598 int win_no;
1599
1600 for (win_no = S3C_FB_MAX_WIN - 1; win_no >= 0; win_no--) {
1601 win = sfb->windows[win_no];
1602 if (!win)
1603 continue;
1604
1605 /* use the blank function to push into power-down */
1606 s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
1607 }
1608 1628
1609 if (!sfb->variant.has_clksel) 1629 if (!sfb->variant.has_clksel)
1610 clk_disable(sfb->lcd_clk); 1630 clk_disable(sfb->lcd_clk);
1611 1631
1612 clk_disable(sfb->bus_clk); 1632 clk_disable(sfb->bus_clk);
1633
1613 return 0; 1634 return 0;
1614} 1635}
1615 1636
@@ -1618,8 +1639,6 @@ static int s3c_fb_runtime_resume(struct device *dev)
1618 struct platform_device *pdev = to_platform_device(dev); 1639 struct platform_device *pdev = to_platform_device(dev);
1619 struct s3c_fb *sfb = platform_get_drvdata(pdev); 1640 struct s3c_fb *sfb = platform_get_drvdata(pdev);
1620 struct s3c_fb_platdata *pd = sfb->pdata; 1641 struct s3c_fb_platdata *pd = sfb->pdata;
1621 struct s3c_fb_win *win;
1622 int win_no;
1623 1642
1624 clk_enable(sfb->bus_clk); 1643 clk_enable(sfb->bus_clk);
1625 1644
@@ -1630,39 +1649,10 @@ static int s3c_fb_runtime_resume(struct device *dev)
1630 pd->setup_gpio(); 1649 pd->setup_gpio();
1631 writel(pd->vidcon1, sfb->regs + VIDCON1); 1650 writel(pd->vidcon1, sfb->regs + VIDCON1);
1632 1651
1633 /* zero all windows before we do anything */
1634 for (win_no = 0; win_no < sfb->variant.nr_windows; win_no++)
1635 s3c_fb_clear_win(sfb, win_no);
1636
1637 for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) {
1638 void __iomem *regs = sfb->regs + sfb->variant.keycon;
1639
1640 regs += (win_no * 8);
1641 writel(0xffffff, regs + WKEYCON0);
1642 writel(0xffffff, regs + WKEYCON1);
1643 }
1644
1645 /* restore framebuffers */
1646 for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) {
1647 win = sfb->windows[win_no];
1648 if (!win)
1649 continue;
1650
1651 dev_dbg(&pdev->dev, "resuming window %d\n", win_no);
1652 s3c_fb_set_par(win->fbinfo);
1653 }
1654
1655 return 0; 1652 return 0;
1656} 1653}
1657
1658#else
1659#define s3c_fb_suspend NULL
1660#define s3c_fb_resume NULL
1661#define s3c_fb_runtime_suspend NULL
1662#define s3c_fb_runtime_resume NULL
1663#endif 1654#endif
1664 1655
1665
1666#define VALID_BPP124 (VALID_BPP(1) | VALID_BPP(2) | VALID_BPP(4)) 1656#define VALID_BPP124 (VALID_BPP(1) | VALID_BPP(2) | VALID_BPP(4))
1667#define VALID_BPP1248 (VALID_BPP124 | VALID_BPP(8)) 1657#define VALID_BPP1248 (VALID_BPP124 | VALID_BPP(8))
1668 1658
@@ -1985,10 +1975,9 @@ static struct platform_device_id s3c_fb_driver_ids[] = {
1985MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids); 1975MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids);
1986 1976
1987static const struct dev_pm_ops s3cfb_pm_ops = { 1977static const struct dev_pm_ops s3cfb_pm_ops = {
1988 .suspend = s3c_fb_suspend, 1978 SET_SYSTEM_SLEEP_PM_OPS(s3c_fb_suspend, s3c_fb_resume)
1989 .resume = s3c_fb_resume, 1979 SET_RUNTIME_PM_OPS(s3c_fb_runtime_suspend, s3c_fb_runtime_resume,
1990 .runtime_suspend = s3c_fb_runtime_suspend, 1980 NULL)
1991 .runtime_resume = s3c_fb_runtime_resume,
1992}; 1981};
1993 1982
1994static struct platform_driver s3c_fb_driver = { 1983static struct platform_driver s3c_fb_driver = {
@@ -2002,18 +1991,7 @@ static struct platform_driver s3c_fb_driver = {
2002 }, 1991 },
2003}; 1992};
2004 1993
2005static int __init s3c_fb_init(void) 1994module_platform_driver(s3c_fb_driver);
2006{
2007 return platform_driver_register(&s3c_fb_driver);
2008}
2009
2010static void __exit s3c_fb_cleanup(void)
2011{
2012 platform_driver_unregister(&s3c_fb_driver);
2013}
2014
2015module_init(s3c_fb_init);
2016module_exit(s3c_fb_cleanup);
2017 1995
2018MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); 1996MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
2019MODULE_DESCRIPTION("Samsung S3C SoC Framebuffer driver"); 1997MODULE_DESCRIPTION("Samsung S3C SoC Framebuffer driver");
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index ee4c0df217f7..77f34c614c86 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -26,8 +26,8 @@
26#include <linux/platform_device.h> 26#include <linux/platform_device.h>
27#include <linux/clk.h> 27#include <linux/clk.h>
28#include <linux/cpufreq.h> 28#include <linux/cpufreq.h>
29#include <linux/io.h>
29 30
30#include <asm/io.h>
31#include <asm/div64.h> 31#include <asm/div64.h>
32 32
33#include <asm/mach/map.h> 33#include <asm/mach/map.h>
@@ -45,10 +45,10 @@
45#ifdef CONFIG_FB_S3C2410_DEBUG 45#ifdef CONFIG_FB_S3C2410_DEBUG
46static int debug = 1; 46static int debug = 1;
47#else 47#else
48static int debug = 0; 48static int debug;
49#endif 49#endif
50 50
51#define dprintk(msg...) if (debug) { printk(KERN_DEBUG "s3c2410fb: " msg); } 51#define dprintk(msg...) if (debug) printk(KERN_DEBUG "s3c2410fb: " msg);
52 52
53/* useful functions */ 53/* useful functions */
54 54
@@ -567,11 +567,10 @@ static int s3c2410fb_blank(int blank_mode, struct fb_info *info)
567 567
568 tpal_reg += is_s3c2412(fbi) ? S3C2412_TPAL : S3C2410_TPAL; 568 tpal_reg += is_s3c2412(fbi) ? S3C2412_TPAL : S3C2410_TPAL;
569 569
570 if (blank_mode == FB_BLANK_POWERDOWN) { 570 if (blank_mode == FB_BLANK_POWERDOWN)
571 s3c2410fb_lcd_enable(fbi, 0); 571 s3c2410fb_lcd_enable(fbi, 0);
572 } else { 572 else
573 s3c2410fb_lcd_enable(fbi, 1); 573 s3c2410fb_lcd_enable(fbi, 1);
574 }
575 574
576 if (blank_mode == FB_BLANK_UNBLANK) 575 if (blank_mode == FB_BLANK_UNBLANK)
577 writel(0x0, tpal_reg); 576 writel(0x0, tpal_reg);
@@ -812,7 +811,7 @@ static inline void s3c2410fb_cpufreq_deregister(struct s3c2410fb_info *info)
812#endif 811#endif
813 812
814 813
815static char driver_name[] = "s3c2410fb"; 814static const char driver_name[] = "s3c2410fb";
816 815
817static int __devinit s3c24xxfb_probe(struct platform_device *pdev, 816static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
818 enum s3c_drv_type drv_type) 817 enum s3c_drv_type drv_type)
@@ -881,7 +880,10 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
881 goto release_mem; 880 goto release_mem;
882 } 881 }
883 882
884 info->irq_base = info->io + ((drv_type == DRV_S3C2412) ? S3C2412_LCDINTBASE : S3C2410_LCDINTBASE); 883 if (drv_type == DRV_S3C2412)
884 info->irq_base = info->io + S3C2412_LCDINTBASE;
885 else
886 info->irq_base = info->io + S3C2410_LCDINTBASE;
885 887
886 dprintk("devinit\n"); 888 dprintk("devinit\n");
887 889
@@ -927,7 +929,7 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
927 clk_enable(info->clk); 929 clk_enable(info->clk);
928 dprintk("got and enabled clock\n"); 930 dprintk("got and enabled clock\n");
929 931
930 msleep(1); 932 usleep_range(1000, 1000);
931 933
932 info->clk_rate = clk_get_rate(info->clk); 934 info->clk_rate = clk_get_rate(info->clk);
933 935
@@ -975,9 +977,8 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
975 977
976 /* create device files */ 978 /* create device files */
977 ret = device_create_file(&pdev->dev, &dev_attr_debug); 979 ret = device_create_file(&pdev->dev, &dev_attr_debug);
978 if (ret) { 980 if (ret)
979 printk(KERN_ERR "failed to add debug attribute\n"); 981 printk(KERN_ERR "failed to add debug attribute\n");
980 }
981 982
982 printk(KERN_INFO "fb%d: %s frame buffer device\n", 983 printk(KERN_INFO "fb%d: %s frame buffer device\n",
983 fbinfo->node, fbinfo->fix.id); 984 fbinfo->node, fbinfo->fix.id);
@@ -1027,7 +1028,7 @@ static int __devexit s3c2410fb_remove(struct platform_device *pdev)
1027 s3c2410fb_cpufreq_deregister(info); 1028 s3c2410fb_cpufreq_deregister(info);
1028 1029
1029 s3c2410fb_lcd_enable(info, 0); 1030 s3c2410fb_lcd_enable(info, 0);
1030 msleep(1); 1031 usleep_range(1000, 1000);
1031 1032
1032 s3c2410fb_unmap_video_memory(fbinfo); 1033 s3c2410fb_unmap_video_memory(fbinfo);
1033 1034
@@ -1064,7 +1065,7 @@ static int s3c2410fb_suspend(struct platform_device *dev, pm_message_t state)
1064 * the LCD DMA engine is not going to get back on the bus 1065 * the LCD DMA engine is not going to get back on the bus
1065 * before the clock goes off again (bjd) */ 1066 * before the clock goes off again (bjd) */
1066 1067
1067 msleep(1); 1068 usleep_range(1000, 1000);
1068 clk_disable(info->clk); 1069 clk_disable(info->clk);
1069 1070
1070 return 0; 1071 return 0;
@@ -1076,7 +1077,7 @@ static int s3c2410fb_resume(struct platform_device *dev)
1076 struct s3c2410fb_info *info = fbinfo->par; 1077 struct s3c2410fb_info *info = fbinfo->par;
1077 1078
1078 clk_enable(info->clk); 1079 clk_enable(info->clk);
1079 msleep(1); 1080 usleep_range(1000, 1000);
1080 1081
1081 s3c2410fb_init_registers(fbinfo); 1082 s3c2410fb_init_registers(fbinfo);
1082 1083
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c
index 946a949f4c7d..2c80246b18b8 100644
--- a/drivers/video/s3fb.c
+++ b/drivers/video/s3fb.c
@@ -727,7 +727,7 @@ static int s3fb_set_par(struct fb_info *info)
727 if (par->chip == CHIP_988_VIRGE_VX) { 727 if (par->chip == CHIP_988_VIRGE_VX) {
728 vga_wcrt(par->state.vgabase, 0x50, 0x00); 728 vga_wcrt(par->state.vgabase, 0x50, 0x00);
729 vga_wcrt(par->state.vgabase, 0x67, 0x50); 729 vga_wcrt(par->state.vgabase, 0x67, 0x50);
730 730 msleep(10); /* screen remains blank sometimes without this */
731 vga_wcrt(par->state.vgabase, 0x63, (mode <= 2) ? 0x90 : 0x09); 731 vga_wcrt(par->state.vgabase, 0x63, (mode <= 2) ? 0x90 : 0x09);
732 vga_wcrt(par->state.vgabase, 0x66, 0x90); 732 vga_wcrt(par->state.vgabase, 0x66, 0x90);
733 } 733 }
@@ -901,7 +901,8 @@ static int s3fb_set_par(struct fb_info *info)
901 901
902 /* Set Data Transfer Position */ 902 /* Set Data Transfer Position */
903 hsstart = ((info->var.xres + info->var.right_margin) * hmul) / 8; 903 hsstart = ((info->var.xres + info->var.right_margin) * hmul) / 8;
904 value = clamp((htotal + hsstart + 1) / 2, hsstart + 4, htotal + 1); 904 /* + 2 is needed for Virge/VX, does no harm on other cards */
905 value = clamp((htotal + hsstart + 1) / 2 + 2, hsstart + 4, htotal + 1);
905 svga_wcrt_multi(par->state.vgabase, s3_dtpc_regs, value); 906 svga_wcrt_multi(par->state.vgabase, s3_dtpc_regs, value);
906 907
907 memset_io(info->screen_base, 0x00, screen_size); 908 memset_io(info->screen_base, 0x00, screen_size);
@@ -1216,6 +1217,31 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i
1216 info->screen_size = 2 << 20; 1217 info->screen_size = 2 << 20;
1217 break; 1218 break;
1218 } 1219 }
1220 } else if (par->chip == CHIP_988_VIRGE_VX) {
1221 switch ((regval & 0x60) >> 5) {
1222 case 0: /* 2MB */
1223 info->screen_size = 2 << 20;
1224 break;
1225 case 1: /* 4MB */
1226 info->screen_size = 4 << 20;
1227 break;
1228 case 2: /* 6MB */
1229 info->screen_size = 6 << 20;
1230 break;
1231 case 3: /* 8MB */
1232 info->screen_size = 8 << 20;
1233 break;
1234 }
1235 /* off-screen memory */
1236 regval = vga_rcrt(par->state.vgabase, 0x37);
1237 switch ((regval & 0x60) >> 5) {
1238 case 1: /* 4MB */
1239 info->screen_size -= 4 << 20;
1240 break;
1241 case 2: /* 2MB */
1242 info->screen_size -= 2 << 20;
1243 break;
1244 }
1219 } else 1245 } else
1220 info->screen_size = s3_memsizes[regval >> 5] << 10; 1246 info->screen_size = s3_memsizes[regval >> 5] << 10;
1221 info->fix.smem_len = info->screen_size; 1247 info->fix.smem_len = info->screen_size;
diff --git a/drivers/video/sbuslib.c b/drivers/video/sbuslib.c
index 37d764ad56b0..3c1de981a18c 100644
--- a/drivers/video/sbuslib.c
+++ b/drivers/video/sbuslib.c
@@ -76,7 +76,7 @@ int sbusfb_mmap_helper(struct sbus_mmap_map *map,
76 map_offset = (physbase + map[i].poff) & POFF_MASK; 76 map_offset = (physbase + map[i].poff) & POFF_MASK;
77 break; 77 break;
78 } 78 }
79 if (!map_size){ 79 if (!map_size) {
80 page += PAGE_SIZE; 80 page += PAGE_SIZE;
81 continue; 81 continue;
82 } 82 }
diff --git a/drivers/video/sh7760fb.c b/drivers/video/sh7760fb.c
index 45e47d847163..83b16e237a0e 100644
--- a/drivers/video/sh7760fb.c
+++ b/drivers/video/sh7760fb.c
@@ -585,18 +585,7 @@ static struct platform_driver sh7760_lcdc_driver = {
585 .remove = __devexit_p(sh7760fb_remove), 585 .remove = __devexit_p(sh7760fb_remove),
586}; 586};
587 587
588static int __init sh7760fb_init(void) 588module_platform_driver(sh7760_lcdc_driver);
589{
590 return platform_driver_register(&sh7760_lcdc_driver);
591}
592
593static void __exit sh7760fb_exit(void)
594{
595 platform_driver_unregister(&sh7760_lcdc_driver);
596}
597
598module_init(sh7760fb_init);
599module_exit(sh7760fb_exit);
600 589
601MODULE_AUTHOR("Nobuhiro Iwamatsu, Manuel Lauss"); 590MODULE_AUTHOR("Nobuhiro Iwamatsu, Manuel Lauss");
602MODULE_DESCRIPTION("FBdev for SH7760/63 integrated LCD Controller"); 591MODULE_DESCRIPTION("FBdev for SH7760/63 integrated LCD Controller");
diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/sh_mipi_dsi.c
index 72ee96bc6b3e..05151b82f40f 100644
--- a/drivers/video/sh_mipi_dsi.c
+++ b/drivers/video/sh_mipi_dsi.c
@@ -8,6 +8,7 @@
8 * published by the Free Software Foundation. 8 * published by the Free Software Foundation.
9 */ 9 */
10 10
11#include <linux/bitmap.h>
11#include <linux/clk.h> 12#include <linux/clk.h>
12#include <linux/delay.h> 13#include <linux/delay.h>
13#include <linux/init.h> 14#include <linux/init.h>
@@ -41,6 +42,7 @@
41#define VMCTR1 0x0020 42#define VMCTR1 0x0020
42#define VMCTR2 0x0024 43#define VMCTR2 0x0024
43#define VMLEN1 0x0028 44#define VMLEN1 0x0028
45#define VMLEN2 0x002c
44#define CMTSRTREQ 0x0070 46#define CMTSRTREQ 0x0070
45#define CMTSRTCTR 0x00d0 47#define CMTSRTCTR 0x00d0
46 48
@@ -51,8 +53,7 @@ struct sh_mipi {
51 void __iomem *base; 53 void __iomem *base;
52 void __iomem *linkbase; 54 void __iomem *linkbase;
53 struct clk *dsit_clk; 55 struct clk *dsit_clk;
54 struct clk *dsip_clk; 56 struct platform_device *pdev;
55 struct device *dev;
56 57
57 void *next_board_data; 58 void *next_board_data;
58 void (*next_display_on)(void *board_data, struct fb_info *info); 59 void (*next_display_on)(void *board_data, struct fb_info *info);
@@ -124,35 +125,15 @@ static void sh_mipi_shutdown(struct platform_device *pdev)
124 sh_mipi_dsi_enable(mipi, false); 125 sh_mipi_dsi_enable(mipi, false);
125} 126}
126 127
127static void mipi_display_on(void *arg, struct fb_info *info)
128{
129 struct sh_mipi *mipi = arg;
130
131 pm_runtime_get_sync(mipi->dev);
132 sh_mipi_dsi_enable(mipi, true);
133
134 if (mipi->next_display_on)
135 mipi->next_display_on(mipi->next_board_data, info);
136}
137
138static void mipi_display_off(void *arg)
139{
140 struct sh_mipi *mipi = arg;
141
142 if (mipi->next_display_off)
143 mipi->next_display_off(mipi->next_board_data);
144
145 sh_mipi_dsi_enable(mipi, false);
146 pm_runtime_put(mipi->dev);
147}
148
149static int __init sh_mipi_setup(struct sh_mipi *mipi, 128static int __init sh_mipi_setup(struct sh_mipi *mipi,
150 struct sh_mipi_dsi_info *pdata) 129 struct sh_mipi_dsi_info *pdata)
151{ 130{
152 void __iomem *base = mipi->base; 131 void __iomem *base = mipi->base;
153 struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan; 132 struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan;
154 u32 pctype, datatype, pixfmt, linelength, vmctr2 = 0x00e00000; 133 u32 pctype, datatype, pixfmt, linelength, vmctr2;
134 u32 tmp, top, bottom, delay, div;
155 bool yuv; 135 bool yuv;
136 int bpp;
156 137
157 /* 138 /*
158 * Select data format. MIPI DSI is not hot-pluggable, so, we just use 139 * Select data format. MIPI DSI is not hot-pluggable, so, we just use
@@ -253,6 +234,9 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
253 (!yuv && ch->interface_type != RGB24)) 234 (!yuv && ch->interface_type != RGB24))
254 return -EINVAL; 235 return -EINVAL;
255 236
237 if (!pdata->lane)
238 return -EINVAL;
239
256 /* reset DSI link */ 240 /* reset DSI link */
257 iowrite32(0x00000001, base + SYSCTRL); 241 iowrite32(0x00000001, base + SYSCTRL);
258 /* Hold reset for 100 cycles of the slowest of bus, HS byte and LP clock */ 242 /* Hold reset for 100 cycles of the slowest of bus, HS byte and LP clock */
@@ -262,15 +246,6 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
262 /* setup DSI link */ 246 /* setup DSI link */
263 247
264 /* 248 /*
265 * Default = ULPS enable |
266 * Contention detection enabled |
267 * EoT packet transmission enable |
268 * CRC check enable |
269 * ECC check enable
270 * additionally enable first two lanes
271 */
272 iowrite32(0x00003703, base + SYSCONF);
273 /*
274 * T_wakeup = 0x7000 249 * T_wakeup = 0x7000
275 * T_hs-trail = 3 250 * T_hs-trail = 3
276 * T_hs-prepare = 3 251 * T_hs-prepare = 3
@@ -290,15 +265,24 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
290 iowrite32(0x0fffffff, base + TATOVSET); 265 iowrite32(0x0fffffff, base + TATOVSET);
291 /* Peripheral reset timeout, default 0xffffffff */ 266 /* Peripheral reset timeout, default 0xffffffff */
292 iowrite32(0x0fffffff, base + PRTOVSET); 267 iowrite32(0x0fffffff, base + PRTOVSET);
293 /* Enable timeout counters */
294 iowrite32(0x00000f00, base + DSICTRL);
295 /* Interrupts not used, disable all */ 268 /* Interrupts not used, disable all */
296 iowrite32(0, base + DSIINTE); 269 iowrite32(0, base + DSIINTE);
297 /* DSI-Tx bias on */ 270 /* DSI-Tx bias on */
298 iowrite32(0x00000001, base + PHYCTRL); 271 iowrite32(0x00000001, base + PHYCTRL);
299 udelay(200); 272 udelay(200);
300 /* Deassert resets, power on, set multiplier */ 273 /* Deassert resets, power on */
301 iowrite32(0x03070b01, base + PHYCTRL); 274 iowrite32(0x03070001, base + PHYCTRL);
275
276 /*
277 * Default = ULPS enable |
278 * Contention detection enabled |
279 * EoT packet transmission enable |
280 * CRC check enable |
281 * ECC check enable
282 */
283 bitmap_fill((unsigned long *)&tmp, pdata->lane);
284 tmp |= 0x00003700;
285 iowrite32(tmp, base + SYSCONF);
302 286
303 /* setup l-bridge */ 287 /* setup l-bridge */
304 288
@@ -316,18 +300,68 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
316 * Non-burst mode with sync pulses: VSE and HSE are output, 300 * Non-burst mode with sync pulses: VSE and HSE are output,
317 * HSA period allowed, no commands in LP 301 * HSA period allowed, no commands in LP
318 */ 302 */
303 vmctr2 = 0;
304 if (pdata->flags & SH_MIPI_DSI_VSEE)
305 vmctr2 |= 1 << 23;
306 if (pdata->flags & SH_MIPI_DSI_HSEE)
307 vmctr2 |= 1 << 22;
308 if (pdata->flags & SH_MIPI_DSI_HSAE)
309 vmctr2 |= 1 << 21;
310 if (pdata->flags & SH_MIPI_DSI_BL2E)
311 vmctr2 |= 1 << 17;
319 if (pdata->flags & SH_MIPI_DSI_HSABM) 312 if (pdata->flags & SH_MIPI_DSI_HSABM)
320 vmctr2 |= 0x20; 313 vmctr2 |= 1 << 5;
321 if (pdata->flags & SH_MIPI_DSI_HSPBM) 314 if (pdata->flags & SH_MIPI_DSI_HBPBM)
322 vmctr2 |= 0x10; 315 vmctr2 |= 1 << 4;
316 if (pdata->flags & SH_MIPI_DSI_HFPBM)
317 vmctr2 |= 1 << 3;
323 iowrite32(vmctr2, mipi->linkbase + VMCTR2); 318 iowrite32(vmctr2, mipi->linkbase + VMCTR2);
324 319
325 /* 320 /*
326 * 0x660 = 1632 bytes per line (RGB24, 544 pixels: see 321 * VMLEN1 = RGBLEN | HSALEN
327 * sh_mobile_lcdc_info.ch[0].lcd_cfg[0].xres), HSALEN = 1 - default 322 *
328 * (unused if VMCTR2[HSABM] = 0) 323 * see
324 * Video mode - Blanking Packet setting
325 */
326 top = linelength << 16; /* RGBLEN */
327 bottom = 0x00000001;
328 if (pdata->flags & SH_MIPI_DSI_HSABM) /* HSALEN */
329 bottom = (pdata->lane * ch->lcd_cfg[0].hsync_len) - 10;
330 iowrite32(top | bottom , mipi->linkbase + VMLEN1);
331
332 /*
333 * VMLEN2 = HBPLEN | HFPLEN
334 *
335 * see
336 * Video mode - Blanking Packet setting
329 */ 337 */
330 iowrite32(1 | (linelength << 16), mipi->linkbase + VMLEN1); 338 top = 0x00010000;
339 bottom = 0x00000001;
340 delay = 0;
341
342 div = 1; /* HSbyteCLK is calculation base
343 * HS4divCLK = HSbyteCLK/2
344 * HS6divCLK is not supported for now */
345 if (pdata->flags & SH_MIPI_DSI_HS4divCLK)
346 div = 2;
347
348 if (pdata->flags & SH_MIPI_DSI_HFPBM) { /* HBPLEN */
349 top = ch->lcd_cfg[0].hsync_len + ch->lcd_cfg[0].left_margin;
350 top = ((pdata->lane * top / div) - 10) << 16;
351 }
352 if (pdata->flags & SH_MIPI_DSI_HBPBM) { /* HFPLEN */
353 bottom = ch->lcd_cfg[0].right_margin;
354 bottom = (pdata->lane * bottom / div) - 12;
355 }
356
357 bpp = linelength / ch->lcd_cfg[0].xres; /* byte / pixel */
358 if ((pdata->lane / div) > bpp) {
359 tmp = ch->lcd_cfg[0].xres / bpp; /* output cycle */
360 tmp = ch->lcd_cfg[0].xres - tmp; /* (input - output) cycle */
361 delay = (pdata->lane * tmp);
362 }
363
364 iowrite32(top | (bottom + delay) , mipi->linkbase + VMLEN2);
331 365
332 msleep(5); 366 msleep(5);
333 367
@@ -352,9 +386,56 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
352 pixfmt << 4); 386 pixfmt << 4);
353 sh_mipi_dcs(ch->chan, MIPI_DCS_SET_DISPLAY_ON); 387 sh_mipi_dcs(ch->chan, MIPI_DCS_SET_DISPLAY_ON);
354 388
389 /* Enable timeout counters */
390 iowrite32(0x00000f00, base + DSICTRL);
391
355 return 0; 392 return 0;
356} 393}
357 394
395static void mipi_display_on(void *arg, struct fb_info *info)
396{
397 struct sh_mipi *mipi = arg;
398 struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data;
399 int ret;
400
401 pm_runtime_get_sync(&mipi->pdev->dev);
402
403 ret = pdata->set_dot_clock(mipi->pdev, mipi->base, 1);
404 if (ret < 0)
405 goto mipi_display_on_fail1;
406
407 ret = sh_mipi_setup(mipi, pdata);
408 if (ret < 0)
409 goto mipi_display_on_fail2;
410
411 sh_mipi_dsi_enable(mipi, true);
412
413 if (mipi->next_display_on)
414 mipi->next_display_on(mipi->next_board_data, info);
415
416 return;
417
418mipi_display_on_fail1:
419 pm_runtime_put_sync(&mipi->pdev->dev);
420mipi_display_on_fail2:
421 pdata->set_dot_clock(mipi->pdev, mipi->base, 0);
422}
423
424static void mipi_display_off(void *arg)
425{
426 struct sh_mipi *mipi = arg;
427 struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data;
428
429 if (mipi->next_display_off)
430 mipi->next_display_off(mipi->next_board_data);
431
432 sh_mipi_dsi_enable(mipi, false);
433
434 pdata->set_dot_clock(mipi->pdev, mipi->base, 0);
435
436 pm_runtime_put_sync(&mipi->pdev->dev);
437}
438
358static int __init sh_mipi_probe(struct platform_device *pdev) 439static int __init sh_mipi_probe(struct platform_device *pdev)
359{ 440{
360 struct sh_mipi *mipi; 441 struct sh_mipi *mipi;
@@ -363,11 +444,13 @@ static int __init sh_mipi_probe(struct platform_device *pdev)
363 struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); 444 struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
364 unsigned long rate, f_current; 445 unsigned long rate, f_current;
365 int idx = pdev->id, ret; 446 int idx = pdev->id, ret;
366 char dsip_clk[] = "dsi.p_clk";
367 447
368 if (!res || !res2 || idx >= ARRAY_SIZE(mipi_dsi) || !pdata) 448 if (!res || !res2 || idx >= ARRAY_SIZE(mipi_dsi) || !pdata)
369 return -ENODEV; 449 return -ENODEV;
370 450
451 if (!pdata->set_dot_clock)
452 return -EINVAL;
453
371 mutex_lock(&array_lock); 454 mutex_lock(&array_lock);
372 if (idx < 0) 455 if (idx < 0)
373 for (idx = 0; idx < ARRAY_SIZE(mipi_dsi) && mipi_dsi[idx]; idx++) 456 for (idx = 0; idx < ARRAY_SIZE(mipi_dsi) && mipi_dsi[idx]; idx++)
@@ -408,7 +491,7 @@ static int __init sh_mipi_probe(struct platform_device *pdev)
408 goto emap2; 491 goto emap2;
409 } 492 }
410 493
411 mipi->dev = &pdev->dev; 494 mipi->pdev = pdev;
412 495
413 mipi->dsit_clk = clk_get(&pdev->dev, "dsit_clk"); 496 mipi->dsit_clk = clk_get(&pdev->dev, "dsit_clk");
414 if (IS_ERR(mipi->dsit_clk)) { 497 if (IS_ERR(mipi->dsit_clk)) {
@@ -428,44 +511,15 @@ static int __init sh_mipi_probe(struct platform_device *pdev)
428 511
429 dev_dbg(&pdev->dev, "DSI-T clk %lu -> %lu\n", f_current, rate); 512 dev_dbg(&pdev->dev, "DSI-T clk %lu -> %lu\n", f_current, rate);
430 513
431 sprintf(dsip_clk, "dsi%1.1dp_clk", idx);
432 mipi->dsip_clk = clk_get(&pdev->dev, dsip_clk);
433 if (IS_ERR(mipi->dsip_clk)) {
434 ret = PTR_ERR(mipi->dsip_clk);
435 goto eclkpget;
436 }
437
438 f_current = clk_get_rate(mipi->dsip_clk);
439 /* Between 10 and 50MHz */
440 rate = clk_round_rate(mipi->dsip_clk, 24000000);
441 if (rate > 0 && rate != f_current)
442 ret = clk_set_rate(mipi->dsip_clk, rate);
443 else
444 ret = rate;
445 if (ret < 0)
446 goto esetprate;
447
448 dev_dbg(&pdev->dev, "DSI-P clk %lu -> %lu\n", f_current, rate);
449
450 msleep(10);
451
452 ret = clk_enable(mipi->dsit_clk); 514 ret = clk_enable(mipi->dsit_clk);
453 if (ret < 0) 515 if (ret < 0)
454 goto eclkton; 516 goto eclkton;
455 517
456 ret = clk_enable(mipi->dsip_clk);
457 if (ret < 0)
458 goto eclkpon;
459
460 mipi_dsi[idx] = mipi; 518 mipi_dsi[idx] = mipi;
461 519
462 pm_runtime_enable(&pdev->dev); 520 pm_runtime_enable(&pdev->dev);
463 pm_runtime_resume(&pdev->dev); 521 pm_runtime_resume(&pdev->dev);
464 522
465 ret = sh_mipi_setup(mipi, pdata);
466 if (ret < 0)
467 goto emipisetup;
468
469 mutex_unlock(&array_lock); 523 mutex_unlock(&array_lock);
470 platform_set_drvdata(pdev, mipi); 524 platform_set_drvdata(pdev, mipi);
471 525
@@ -482,16 +536,7 @@ static int __init sh_mipi_probe(struct platform_device *pdev)
482 536
483 return 0; 537 return 0;
484 538
485emipisetup:
486 mipi_dsi[idx] = NULL;
487 pm_runtime_disable(&pdev->dev);
488 clk_disable(mipi->dsip_clk);
489eclkpon:
490 clk_disable(mipi->dsit_clk);
491eclkton: 539eclkton:
492esetprate:
493 clk_put(mipi->dsip_clk);
494eclkpget:
495esettrate: 540esettrate:
496 clk_put(mipi->dsit_clk); 541 clk_put(mipi->dsit_clk);
497eclktget: 542eclktget:
@@ -542,10 +587,9 @@ static int __exit sh_mipi_remove(struct platform_device *pdev)
542 pdata->lcd_chan->board_cfg.board_data = NULL; 587 pdata->lcd_chan->board_cfg.board_data = NULL;
543 588
544 pm_runtime_disable(&pdev->dev); 589 pm_runtime_disable(&pdev->dev);
545 clk_disable(mipi->dsip_clk);
546 clk_disable(mipi->dsit_clk); 590 clk_disable(mipi->dsit_clk);
547 clk_put(mipi->dsit_clk); 591 clk_put(mipi->dsit_clk);
548 clk_put(mipi->dsip_clk); 592
549 iounmap(mipi->linkbase); 593 iounmap(mipi->linkbase);
550 if (res2) 594 if (res2)
551 release_mem_region(res2->start, resource_size(res2)); 595 release_mem_region(res2->start, resource_size(res2));
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index facffc254976..aac5b369d73c 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -17,6 +17,7 @@
17#include <linux/platform_device.h> 17#include <linux/platform_device.h>
18#include <linux/dma-mapping.h> 18#include <linux/dma-mapping.h>
19#include <linux/interrupt.h> 19#include <linux/interrupt.h>
20#include <linux/videodev2.h>
20#include <linux/vmalloc.h> 21#include <linux/vmalloc.h>
21#include <linux/ioctl.h> 22#include <linux/ioctl.h>
22#include <linux/slab.h> 23#include <linux/slab.h>
@@ -102,7 +103,7 @@ struct sh_mobile_lcdc_priv {
102 struct sh_mobile_lcdc_chan ch[2]; 103 struct sh_mobile_lcdc_chan ch[2];
103 struct notifier_block notifier; 104 struct notifier_block notifier;
104 int started; 105 int started;
105 int forced_bpp; /* 2 channel LCDC must share bpp setting */ 106 int forced_fourcc; /* 2 channel LCDC must share fourcc setting */
106 struct sh_mobile_meram_info *meram_dev; 107 struct sh_mobile_meram_info *meram_dev;
107}; 108};
108 109
@@ -215,6 +216,47 @@ struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
215 lcdc_sys_read_data, 216 lcdc_sys_read_data,
216}; 217};
217 218
219static int sh_mobile_format_fourcc(const struct fb_var_screeninfo *var)
220{
221 if (var->grayscale > 1)
222 return var->grayscale;
223
224 switch (var->bits_per_pixel) {
225 case 16:
226 return V4L2_PIX_FMT_RGB565;
227 case 24:
228 return V4L2_PIX_FMT_BGR24;
229 case 32:
230 return V4L2_PIX_FMT_BGR32;
231 default:
232 return 0;
233 }
234}
235
236static int sh_mobile_format_is_fourcc(const struct fb_var_screeninfo *var)
237{
238 return var->grayscale > 1;
239}
240
241static bool sh_mobile_format_is_yuv(const struct fb_var_screeninfo *var)
242{
243 if (var->grayscale <= 1)
244 return false;
245
246 switch (var->grayscale) {
247 case V4L2_PIX_FMT_NV12:
248 case V4L2_PIX_FMT_NV21:
249 case V4L2_PIX_FMT_NV16:
250 case V4L2_PIX_FMT_NV61:
251 case V4L2_PIX_FMT_NV24:
252 case V4L2_PIX_FMT_NV42:
253 return true;
254
255 default:
256 return false;
257 }
258}
259
218static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv) 260static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv)
219{ 261{
220 if (atomic_inc_and_test(&priv->hw_usecnt)) { 262 if (atomic_inc_and_test(&priv->hw_usecnt)) {
@@ -420,7 +462,7 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
420 tmp = ((display_var->xres & 7) << 24) | 462 tmp = ((display_var->xres & 7) << 24) |
421 ((display_h_total & 7) << 16) | 463 ((display_h_total & 7) << 16) |
422 ((display_var->hsync_len & 7) << 8) | 464 ((display_var->hsync_len & 7) << 8) |
423 hsync_pos; 465 (hsync_pos & 7);
424 lcdc_write_chan(ch, LDHAJR, tmp); 466 lcdc_write_chan(ch, LDHAJR, tmp);
425} 467}
426 468
@@ -435,7 +477,6 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
435{ 477{
436 struct sh_mobile_lcdc_chan *ch; 478 struct sh_mobile_lcdc_chan *ch;
437 unsigned long tmp; 479 unsigned long tmp;
438 int bpp = 0;
439 int k, m; 480 int k, m;
440 481
441 /* Enable LCDC channels. Read data from external memory, avoid using the 482 /* Enable LCDC channels. Read data from external memory, avoid using the
@@ -454,9 +495,6 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
454 if (!ch->enabled) 495 if (!ch->enabled)
455 continue; 496 continue;
456 497
457 if (!bpp)
458 bpp = ch->info->var.bits_per_pixel;
459
460 /* Power supply */ 498 /* Power supply */
461 lcdc_write_chan(ch, LDPMR, 0); 499 lcdc_write_chan(ch, LDPMR, 0);
462 500
@@ -487,31 +525,37 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
487 525
488 sh_mobile_lcdc_geometry(ch); 526 sh_mobile_lcdc_geometry(ch);
489 527
490 if (ch->info->var.nonstd) { 528 switch (sh_mobile_format_fourcc(&ch->info->var)) {
491 tmp = (ch->info->var.nonstd << 16); 529 case V4L2_PIX_FMT_RGB565:
492 switch (ch->info->var.bits_per_pixel) { 530 tmp = LDDFR_PKF_RGB16;
493 case 12: 531 break;
494 tmp |= LDDFR_YF_420; 532 case V4L2_PIX_FMT_BGR24:
495 break; 533 tmp = LDDFR_PKF_RGB24;
496 case 16: 534 break;
497 tmp |= LDDFR_YF_422; 535 case V4L2_PIX_FMT_BGR32:
498 break; 536 tmp = LDDFR_PKF_ARGB32;
499 case 24: 537 break;
500 default: 538 case V4L2_PIX_FMT_NV12:
501 tmp |= LDDFR_YF_444; 539 case V4L2_PIX_FMT_NV21:
502 break; 540 tmp = LDDFR_CC | LDDFR_YF_420;
503 } 541 break;
504 } else { 542 case V4L2_PIX_FMT_NV16:
505 switch (ch->info->var.bits_per_pixel) { 543 case V4L2_PIX_FMT_NV61:
506 case 16: 544 tmp = LDDFR_CC | LDDFR_YF_422;
507 tmp = LDDFR_PKF_RGB16; 545 break;
508 break; 546 case V4L2_PIX_FMT_NV24:
509 case 24: 547 case V4L2_PIX_FMT_NV42:
510 tmp = LDDFR_PKF_RGB24; 548 tmp = LDDFR_CC | LDDFR_YF_444;
549 break;
550 }
551
552 if (sh_mobile_format_is_yuv(&ch->info->var)) {
553 switch (ch->info->var.colorspace) {
554 case V4L2_COLORSPACE_REC709:
555 tmp |= LDDFR_CF1;
511 break; 556 break;
512 case 32: 557 case V4L2_COLORSPACE_JPEG:
513 default: 558 tmp |= LDDFR_CF0;
514 tmp = LDDFR_PKF_ARGB32;
515 break; 559 break;
516 } 560 }
517 } 561 }
@@ -519,7 +563,7 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
519 lcdc_write_chan(ch, LDDFR, tmp); 563 lcdc_write_chan(ch, LDDFR, tmp);
520 lcdc_write_chan(ch, LDMLSR, ch->pitch); 564 lcdc_write_chan(ch, LDMLSR, ch->pitch);
521 lcdc_write_chan(ch, LDSA1R, ch->base_addr_y); 565 lcdc_write_chan(ch, LDSA1R, ch->base_addr_y);
522 if (ch->info->var.nonstd) 566 if (sh_mobile_format_is_yuv(&ch->info->var))
523 lcdc_write_chan(ch, LDSA2R, ch->base_addr_c); 567 lcdc_write_chan(ch, LDSA2R, ch->base_addr_c);
524 568
525 /* When using deferred I/O mode, configure the LCDC for one-shot 569 /* When using deferred I/O mode, configure the LCDC for one-shot
@@ -536,21 +580,23 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
536 } 580 }
537 581
538 /* Word and long word swap. */ 582 /* Word and long word swap. */
539 if (priv->ch[0].info->var.nonstd) 583 switch (sh_mobile_format_fourcc(&priv->ch[0].info->var)) {
584 case V4L2_PIX_FMT_RGB565:
585 case V4L2_PIX_FMT_NV21:
586 case V4L2_PIX_FMT_NV61:
587 case V4L2_PIX_FMT_NV42:
588 tmp = LDDDSR_LS | LDDDSR_WS;
589 break;
590 case V4L2_PIX_FMT_BGR24:
591 case V4L2_PIX_FMT_NV12:
592 case V4L2_PIX_FMT_NV16:
593 case V4L2_PIX_FMT_NV24:
540 tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS; 594 tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
541 else { 595 break;
542 switch (bpp) { 596 case V4L2_PIX_FMT_BGR32:
543 case 16: 597 default:
544 tmp = LDDDSR_LS | LDDDSR_WS; 598 tmp = LDDDSR_LS;
545 break; 599 break;
546 case 24:
547 tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
548 break;
549 case 32:
550 default:
551 tmp = LDDDSR_LS;
552 break;
553 }
554 } 600 }
555 lcdc_write(priv, _LDDDSR, tmp); 601 lcdc_write(priv, _LDDDSR, tmp);
556 602
@@ -622,12 +668,24 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
622 ch->meram_enabled = 0; 668 ch->meram_enabled = 0;
623 } 669 }
624 670
625 if (!ch->info->var.nonstd) 671 switch (sh_mobile_format_fourcc(&ch->info->var)) {
626 pixelformat = SH_MOBILE_MERAM_PF_RGB; 672 case V4L2_PIX_FMT_NV12:
627 else if (ch->info->var.bits_per_pixel == 24) 673 case V4L2_PIX_FMT_NV21:
628 pixelformat = SH_MOBILE_MERAM_PF_NV24; 674 case V4L2_PIX_FMT_NV16:
629 else 675 case V4L2_PIX_FMT_NV61:
630 pixelformat = SH_MOBILE_MERAM_PF_NV; 676 pixelformat = SH_MOBILE_MERAM_PF_NV;
677 break;
678 case V4L2_PIX_FMT_NV24:
679 case V4L2_PIX_FMT_NV42:
680 pixelformat = SH_MOBILE_MERAM_PF_NV24;
681 break;
682 case V4L2_PIX_FMT_RGB565:
683 case V4L2_PIX_FMT_BGR24:
684 case V4L2_PIX_FMT_BGR32:
685 default:
686 pixelformat = SH_MOBILE_MERAM_PF_RGB;
687 break;
688 }
631 689
632 ret = mdev->ops->meram_register(mdev, cfg, ch->pitch, 690 ret = mdev->ops->meram_register(mdev, cfg, ch->pitch,
633 ch->info->var.yres, pixelformat, 691 ch->info->var.yres, pixelformat,
@@ -845,6 +903,7 @@ static struct fb_fix_screeninfo sh_mobile_lcdc_fix = {
845 .xpanstep = 0, 903 .xpanstep = 0,
846 .ypanstep = 1, 904 .ypanstep = 1,
847 .ywrapstep = 0, 905 .ywrapstep = 0,
906 .capabilities = FB_CAP_FOURCC,
848}; 907};
849 908
850static void sh_mobile_lcdc_fillrect(struct fb_info *info, 909static void sh_mobile_lcdc_fillrect(struct fb_info *info,
@@ -877,8 +936,9 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
877 unsigned long new_pan_offset; 936 unsigned long new_pan_offset;
878 unsigned long base_addr_y, base_addr_c; 937 unsigned long base_addr_y, base_addr_c;
879 unsigned long c_offset; 938 unsigned long c_offset;
939 bool yuv = sh_mobile_format_is_yuv(&info->var);
880 940
881 if (!info->var.nonstd) 941 if (!yuv)
882 new_pan_offset = var->yoffset * info->fix.line_length 942 new_pan_offset = var->yoffset * info->fix.line_length
883 + var->xoffset * (info->var.bits_per_pixel / 8); 943 + var->xoffset * (info->var.bits_per_pixel / 8);
884 else 944 else
@@ -892,7 +952,7 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
892 952
893 /* Set the source address for the next refresh */ 953 /* Set the source address for the next refresh */
894 base_addr_y = ch->dma_handle + new_pan_offset; 954 base_addr_y = ch->dma_handle + new_pan_offset;
895 if (info->var.nonstd) { 955 if (yuv) {
896 /* Set y offset */ 956 /* Set y offset */
897 c_offset = var->yoffset * info->fix.line_length 957 c_offset = var->yoffset * info->fix.line_length
898 * (info->var.bits_per_pixel - 8) / 8; 958 * (info->var.bits_per_pixel - 8) / 8;
@@ -900,7 +960,7 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
900 + info->var.xres * info->var.yres_virtual 960 + info->var.xres * info->var.yres_virtual
901 + c_offset; 961 + c_offset;
902 /* Set x offset */ 962 /* Set x offset */
903 if (info->var.bits_per_pixel == 24) 963 if (sh_mobile_format_fourcc(&info->var) == V4L2_PIX_FMT_NV24)
904 base_addr_c += 2 * var->xoffset; 964 base_addr_c += 2 * var->xoffset;
905 else 965 else
906 base_addr_c += var->xoffset; 966 base_addr_c += var->xoffset;
@@ -924,7 +984,7 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
924 ch->base_addr_c = base_addr_c; 984 ch->base_addr_c = base_addr_c;
925 985
926 lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y); 986 lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
927 if (info->var.nonstd) 987 if (yuv)
928 lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c); 988 lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
929 989
930 if (lcdc_chan_is_sublcd(ch)) 990 if (lcdc_chan_is_sublcd(ch))
@@ -1100,51 +1160,84 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in
1100 if (var->yres_virtual < var->yres) 1160 if (var->yres_virtual < var->yres)
1101 var->yres_virtual = var->yres; 1161 var->yres_virtual = var->yres;
1102 1162
1103 if (var->bits_per_pixel <= 16) { /* RGB 565 */ 1163 if (sh_mobile_format_is_fourcc(var)) {
1104 var->bits_per_pixel = 16; 1164 switch (var->grayscale) {
1105 var->red.offset = 11; 1165 case V4L2_PIX_FMT_NV12:
1106 var->red.length = 5; 1166 case V4L2_PIX_FMT_NV21:
1107 var->green.offset = 5; 1167 var->bits_per_pixel = 12;
1108 var->green.length = 6; 1168 break;
1109 var->blue.offset = 0; 1169 case V4L2_PIX_FMT_RGB565:
1110 var->blue.length = 5; 1170 case V4L2_PIX_FMT_NV16:
1111 var->transp.offset = 0; 1171 case V4L2_PIX_FMT_NV61:
1112 var->transp.length = 0; 1172 var->bits_per_pixel = 16;
1113 } else if (var->bits_per_pixel <= 24) { /* RGB 888 */ 1173 break;
1114 var->bits_per_pixel = 24; 1174 case V4L2_PIX_FMT_BGR24:
1115 var->red.offset = 16; 1175 case V4L2_PIX_FMT_NV24:
1116 var->red.length = 8; 1176 case V4L2_PIX_FMT_NV42:
1117 var->green.offset = 8; 1177 var->bits_per_pixel = 24;
1118 var->green.length = 8; 1178 break;
1119 var->blue.offset = 0; 1179 case V4L2_PIX_FMT_BGR32:
1120 var->blue.length = 8; 1180 var->bits_per_pixel = 32;
1121 var->transp.offset = 0; 1181 break;
1122 var->transp.length = 0; 1182 default:
1123 } else if (var->bits_per_pixel <= 32) { /* RGBA 888 */ 1183 return -EINVAL;
1124 var->bits_per_pixel = 32; 1184 }
1125 var->red.offset = 16;
1126 var->red.length = 8;
1127 var->green.offset = 8;
1128 var->green.length = 8;
1129 var->blue.offset = 0;
1130 var->blue.length = 8;
1131 var->transp.offset = 24;
1132 var->transp.length = 8;
1133 } else
1134 return -EINVAL;
1135 1185
1136 var->red.msb_right = 0; 1186 /* Default to RGB and JPEG color-spaces for RGB and YUV formats
1137 var->green.msb_right = 0; 1187 * respectively.
1138 var->blue.msb_right = 0; 1188 */
1139 var->transp.msb_right = 0; 1189 if (!sh_mobile_format_is_yuv(var))
1190 var->colorspace = V4L2_COLORSPACE_SRGB;
1191 else if (var->colorspace != V4L2_COLORSPACE_REC709)
1192 var->colorspace = V4L2_COLORSPACE_JPEG;
1193 } else {
1194 if (var->bits_per_pixel <= 16) { /* RGB 565 */
1195 var->bits_per_pixel = 16;
1196 var->red.offset = 11;
1197 var->red.length = 5;
1198 var->green.offset = 5;
1199 var->green.length = 6;
1200 var->blue.offset = 0;
1201 var->blue.length = 5;
1202 var->transp.offset = 0;
1203 var->transp.length = 0;
1204 } else if (var->bits_per_pixel <= 24) { /* RGB 888 */
1205 var->bits_per_pixel = 24;
1206 var->red.offset = 16;
1207 var->red.length = 8;
1208 var->green.offset = 8;
1209 var->green.length = 8;
1210 var->blue.offset = 0;
1211 var->blue.length = 8;
1212 var->transp.offset = 0;
1213 var->transp.length = 0;
1214 } else if (var->bits_per_pixel <= 32) { /* RGBA 888 */
1215 var->bits_per_pixel = 32;
1216 var->red.offset = 16;
1217 var->red.length = 8;
1218 var->green.offset = 8;
1219 var->green.length = 8;
1220 var->blue.offset = 0;
1221 var->blue.length = 8;
1222 var->transp.offset = 24;
1223 var->transp.length = 8;
1224 } else
1225 return -EINVAL;
1226
1227 var->red.msb_right = 0;
1228 var->green.msb_right = 0;
1229 var->blue.msb_right = 0;
1230 var->transp.msb_right = 0;
1231 }
1140 1232
1141 /* Make sure we don't exceed our allocated memory. */ 1233 /* Make sure we don't exceed our allocated memory. */
1142 if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 > 1234 if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 >
1143 info->fix.smem_len) 1235 info->fix.smem_len)
1144 return -EINVAL; 1236 return -EINVAL;
1145 1237
1146 /* only accept the forced_bpp for dual channel configurations */ 1238 /* only accept the forced_fourcc for dual channel configurations */
1147 if (p->forced_bpp && p->forced_bpp != var->bits_per_pixel) 1239 if (p->forced_fourcc &&
1240 p->forced_fourcc != sh_mobile_format_fourcc(var))
1148 return -EINVAL; 1241 return -EINVAL;
1149 1242
1150 return 0; 1243 return 0;
@@ -1158,7 +1251,7 @@ static int sh_mobile_set_par(struct fb_info *info)
1158 1251
1159 sh_mobile_lcdc_stop(ch->lcdc); 1252 sh_mobile_lcdc_stop(ch->lcdc);
1160 1253
1161 if (info->var.nonstd) 1254 if (sh_mobile_format_is_yuv(&info->var))
1162 info->fix.line_length = info->var.xres; 1255 info->fix.line_length = info->var.xres;
1163 else 1256 else
1164 info->fix.line_length = info->var.xres 1257 info->fix.line_length = info->var.xres
@@ -1170,6 +1263,14 @@ static int sh_mobile_set_par(struct fb_info *info)
1170 info->fix.line_length = line_length; 1263 info->fix.line_length = line_length;
1171 } 1264 }
1172 1265
1266 if (sh_mobile_format_is_fourcc(&info->var)) {
1267 info->fix.type = FB_TYPE_FOURCC;
1268 info->fix.visual = FB_VISUAL_FOURCC;
1269 } else {
1270 info->fix.type = FB_TYPE_PACKED_PIXELS;
1271 info->fix.visual = FB_VISUAL_TRUECOLOR;
1272 }
1273
1173 return ret; 1274 return ret;
1174} 1275}
1175 1276
@@ -1464,9 +1565,9 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
1464 for (i = 0, mode = cfg->lcd_cfg; i < cfg->num_cfg; i++, mode++) { 1565 for (i = 0, mode = cfg->lcd_cfg; i < cfg->num_cfg; i++, mode++) {
1465 unsigned int size = mode->yres * mode->xres; 1566 unsigned int size = mode->yres * mode->xres;
1466 1567
1467 /* NV12 buffers must have even number of lines */ 1568 /* NV12/NV21 buffers must have even number of lines */
1468 if ((cfg->nonstd) && cfg->bpp == 12 && 1569 if ((cfg->fourcc == V4L2_PIX_FMT_NV12 ||
1469 (mode->yres & 0x1)) { 1570 cfg->fourcc == V4L2_PIX_FMT_NV21) && (mode->yres & 0x1)) {
1470 dev_err(dev, "yres must be multiple of 2 for YCbCr420 " 1571 dev_err(dev, "yres must be multiple of 2 for YCbCr420 "
1471 "mode.\n"); 1572 "mode.\n");
1472 return -EINVAL; 1573 return -EINVAL;
@@ -1484,14 +1585,6 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
1484 dev_dbg(dev, "Found largest videomode %ux%u\n", 1585 dev_dbg(dev, "Found largest videomode %ux%u\n",
1485 max_mode->xres, max_mode->yres); 1586 max_mode->xres, max_mode->yres);
1486 1587
1487 /* Initialize fixed screen information. Restrict pan to 2 lines steps
1488 * for NV12.
1489 */
1490 info->fix = sh_mobile_lcdc_fix;
1491 info->fix.smem_len = max_size * 2 * cfg->bpp / 8;
1492 if (cfg->nonstd && cfg->bpp == 12)
1493 info->fix.ypanstep = 2;
1494
1495 /* Create the mode list. */ 1588 /* Create the mode list. */
1496 if (cfg->lcd_cfg == NULL) { 1589 if (cfg->lcd_cfg == NULL) {
1497 mode = &default_720p; 1590 mode = &default_720p;
@@ -1509,19 +1602,38 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
1509 */ 1602 */
1510 var = &info->var; 1603 var = &info->var;
1511 fb_videomode_to_var(var, mode); 1604 fb_videomode_to_var(var, mode);
1512 var->bits_per_pixel = cfg->bpp;
1513 var->width = cfg->lcd_size_cfg.width; 1605 var->width = cfg->lcd_size_cfg.width;
1514 var->height = cfg->lcd_size_cfg.height; 1606 var->height = cfg->lcd_size_cfg.height;
1515 var->yres_virtual = var->yres * 2; 1607 var->yres_virtual = var->yres * 2;
1516 var->activate = FB_ACTIVATE_NOW; 1608 var->activate = FB_ACTIVATE_NOW;
1517 1609
1610 switch (cfg->fourcc) {
1611 case V4L2_PIX_FMT_RGB565:
1612 var->bits_per_pixel = 16;
1613 break;
1614 case V4L2_PIX_FMT_BGR24:
1615 var->bits_per_pixel = 24;
1616 break;
1617 case V4L2_PIX_FMT_BGR32:
1618 var->bits_per_pixel = 32;
1619 break;
1620 default:
1621 var->grayscale = cfg->fourcc;
1622 break;
1623 }
1624
1625 /* Make sure the memory size check won't fail. smem_len is initialized
1626 * later based on var.
1627 */
1628 info->fix.smem_len = UINT_MAX;
1518 ret = sh_mobile_check_var(var, info); 1629 ret = sh_mobile_check_var(var, info);
1519 if (ret) 1630 if (ret)
1520 return ret; 1631 return ret;
1521 1632
1633 max_size = max_size * var->bits_per_pixel / 8 * 2;
1634
1522 /* Allocate frame buffer memory and color map. */ 1635 /* Allocate frame buffer memory and color map. */
1523 buf = dma_alloc_coherent(dev, info->fix.smem_len, &ch->dma_handle, 1636 buf = dma_alloc_coherent(dev, max_size, &ch->dma_handle, GFP_KERNEL);
1524 GFP_KERNEL);
1525 if (!buf) { 1637 if (!buf) {
1526 dev_err(dev, "unable to allocate buffer\n"); 1638 dev_err(dev, "unable to allocate buffer\n");
1527 return -ENOMEM; 1639 return -ENOMEM;
@@ -1530,16 +1642,27 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
1530 ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0); 1642 ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
1531 if (ret < 0) { 1643 if (ret < 0) {
1532 dev_err(dev, "unable to allocate cmap\n"); 1644 dev_err(dev, "unable to allocate cmap\n");
1533 dma_free_coherent(dev, info->fix.smem_len, 1645 dma_free_coherent(dev, max_size, buf, ch->dma_handle);
1534 buf, ch->dma_handle);
1535 return ret; 1646 return ret;
1536 } 1647 }
1537 1648
1649 /* Initialize fixed screen information. Restrict pan to 2 lines steps
1650 * for NV12 and NV21.
1651 */
1652 info->fix = sh_mobile_lcdc_fix;
1538 info->fix.smem_start = ch->dma_handle; 1653 info->fix.smem_start = ch->dma_handle;
1539 if (var->nonstd) 1654 info->fix.smem_len = max_size;
1655 if (cfg->fourcc == V4L2_PIX_FMT_NV12 ||
1656 cfg->fourcc == V4L2_PIX_FMT_NV21)
1657 info->fix.ypanstep = 2;
1658
1659 if (sh_mobile_format_is_yuv(var)) {
1540 info->fix.line_length = var->xres; 1660 info->fix.line_length = var->xres;
1541 else 1661 info->fix.visual = FB_VISUAL_FOURCC;
1542 info->fix.line_length = var->xres * (cfg->bpp / 8); 1662 } else {
1663 info->fix.line_length = var->xres * var->bits_per_pixel / 8;
1664 info->fix.visual = FB_VISUAL_TRUECOLOR;
1665 }
1543 1666
1544 info->screen_base = buf; 1667 info->screen_base = buf;
1545 info->device = dev; 1668 info->device = dev;
@@ -1626,9 +1749,9 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1626 goto err1; 1749 goto err1;
1627 } 1750 }
1628 1751
1629 /* for dual channel LCDC (MAIN + SUB) force shared bpp setting */ 1752 /* for dual channel LCDC (MAIN + SUB) force shared format setting */
1630 if (num_channels == 2) 1753 if (num_channels == 2)
1631 priv->forced_bpp = pdata->ch[0].bpp; 1754 priv->forced_fourcc = pdata->ch[0].fourcc;
1632 1755
1633 priv->base = ioremap_nocache(res->start, resource_size(res)); 1756 priv->base = ioremap_nocache(res->start, resource_size(res));
1634 if (!priv->base) 1757 if (!priv->base)
@@ -1675,13 +1798,10 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
1675 if (error < 0) 1798 if (error < 0)
1676 goto err1; 1799 goto err1;
1677 1800
1678 dev_info(info->dev, 1801 dev_info(info->dev, "registered %s/%s as %dx%d %dbpp.\n",
1679 "registered %s/%s as %dx%d %dbpp.\n", 1802 pdev->name, (ch->cfg.chan == LCDC_CHAN_MAINLCD) ?
1680 pdev->name, 1803 "mainlcd" : "sublcd", info->var.xres, info->var.yres,
1681 (ch->cfg.chan == LCDC_CHAN_MAINLCD) ? 1804 info->var.bits_per_pixel);
1682 "mainlcd" : "sublcd",
1683 info->var.xres, info->var.yres,
1684 ch->cfg.bpp);
1685 1805
1686 /* deferred io mode: disable clock to save power */ 1806 /* deferred io mode: disable clock to save power */
1687 if (info->fbdefio || info->state == FBINFO_STATE_SUSPENDED) 1807 if (info->fbdefio || info->state == FBINFO_STATE_SUSPENDED)
@@ -1709,18 +1829,7 @@ static struct platform_driver sh_mobile_lcdc_driver = {
1709 .remove = sh_mobile_lcdc_remove, 1829 .remove = sh_mobile_lcdc_remove,
1710}; 1830};
1711 1831
1712static int __init sh_mobile_lcdc_init(void) 1832module_platform_driver(sh_mobile_lcdc_driver);
1713{
1714 return platform_driver_register(&sh_mobile_lcdc_driver);
1715}
1716
1717static void __exit sh_mobile_lcdc_exit(void)
1718{
1719 platform_driver_unregister(&sh_mobile_lcdc_driver);
1720}
1721
1722module_init(sh_mobile_lcdc_init);
1723module_exit(sh_mobile_lcdc_exit);
1724 1833
1725MODULE_DESCRIPTION("SuperH Mobile LCDC Framebuffer driver"); 1834MODULE_DESCRIPTION("SuperH Mobile LCDC Framebuffer driver");
1726MODULE_AUTHOR("Magnus Damm <damm@opensource.se>"); 1835MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/sh_mobile_meram.c
index 4d63490209cd..f45d83ecfd21 100644
--- a/drivers/video/sh_mobile_meram.c
+++ b/drivers/video/sh_mobile_meram.c
@@ -679,18 +679,7 @@ static struct platform_driver sh_mobile_meram_driver = {
679 .remove = sh_mobile_meram_remove, 679 .remove = sh_mobile_meram_remove,
680}; 680};
681 681
682static int __init sh_mobile_meram_init(void) 682module_platform_driver(sh_mobile_meram_driver);
683{
684 return platform_driver_register(&sh_mobile_meram_driver);
685}
686
687static void __exit sh_mobile_meram_exit(void)
688{
689 platform_driver_unregister(&sh_mobile_meram_driver);
690}
691
692module_init(sh_mobile_meram_init);
693module_exit(sh_mobile_meram_exit);
694 683
695MODULE_DESCRIPTION("SuperH Mobile MERAM driver"); 684MODULE_DESCRIPTION("SuperH Mobile MERAM driver");
696MODULE_AUTHOR("Damian Hobson-Garcia / Takanari Hayama"); 685MODULE_AUTHOR("Damian Hobson-Garcia / Takanari Hayama");
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index a78254cf8e83..3690effbedcc 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -2230,18 +2230,7 @@ static struct platform_driver sm501fb_driver = {
2230 }, 2230 },
2231}; 2231};
2232 2232
2233static int __devinit sm501fb_init(void) 2233module_platform_driver(sm501fb_driver);
2234{
2235 return platform_driver_register(&sm501fb_driver);
2236}
2237
2238static void __exit sm501fb_cleanup(void)
2239{
2240 platform_driver_unregister(&sm501fb_driver);
2241}
2242
2243module_init(sm501fb_init);
2244module_exit(sm501fb_cleanup);
2245 2234
2246module_param_named(mode, fb_mode, charp, 0); 2235module_param_named(mode, fb_mode, charp, 0);
2247MODULE_PARM_DESC(mode, 2236MODULE_PARM_DESC(mode,
diff --git a/drivers/video/vt8500lcdfb.c b/drivers/video/vt8500lcdfb.c
index 777c21dd7a6b..2a5fe6ede845 100644
--- a/drivers/video/vt8500lcdfb.c
+++ b/drivers/video/vt8500lcdfb.c
@@ -457,18 +457,7 @@ static struct platform_driver vt8500lcd_driver = {
457 }, 457 },
458}; 458};
459 459
460static int __init vt8500lcd_init(void) 460module_platform_driver(vt8500lcd_driver);
461{
462 return platform_driver_register(&vt8500lcd_driver);
463}
464
465static void __exit vt8500lcd_exit(void)
466{
467 platform_driver_unregister(&vt8500lcd_driver);
468}
469
470module_init(vt8500lcd_init);
471module_exit(vt8500lcd_exit);
472 461
473MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>"); 462MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
474MODULE_DESCRIPTION("LCD controller driver for VIA VT8500"); 463MODULE_DESCRIPTION("LCD controller driver for VIA VT8500");
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c
index 2375e5bbf572..90a2e30272ad 100644
--- a/drivers/video/w100fb.c
+++ b/drivers/video/w100fb.c
@@ -1620,18 +1620,7 @@ static struct platform_driver w100fb_driver = {
1620 }, 1620 },
1621}; 1621};
1622 1622
1623int __init w100fb_init(void) 1623module_platform_driver(w100fb_driver);
1624{
1625 return platform_driver_register(&w100fb_driver);
1626}
1627
1628void __exit w100fb_cleanup(void)
1629{
1630 platform_driver_unregister(&w100fb_driver);
1631}
1632
1633module_init(w100fb_init);
1634module_exit(w100fb_cleanup);
1635 1624
1636MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver"); 1625MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver");
1637MODULE_LICENSE("GPL"); 1626MODULE_LICENSE("GPL");
diff --git a/drivers/video/wm8505fb.c b/drivers/video/wm8505fb.c
index 96e34a569169..c8703bd61b74 100644
--- a/drivers/video/wm8505fb.c
+++ b/drivers/video/wm8505fb.c
@@ -404,18 +404,7 @@ static struct platform_driver wm8505fb_driver = {
404 }, 404 },
405}; 405};
406 406
407static int __init wm8505fb_init(void) 407module_platform_driver(wm8505fb_driver);
408{
409 return platform_driver_register(&wm8505fb_driver);
410}
411
412static void __exit wm8505fb_exit(void)
413{
414 platform_driver_unregister(&wm8505fb_driver);
415}
416
417module_init(wm8505fb_init);
418module_exit(wm8505fb_exit);
419 408
420MODULE_AUTHOR("Ed Spiridonov <edo.rus@gmail.com>"); 409MODULE_AUTHOR("Ed Spiridonov <edo.rus@gmail.com>");
421MODULE_DESCRIPTION("Framebuffer driver for WMT WM8505"); 410MODULE_DESCRIPTION("Framebuffer driver for WMT WM8505");
diff --git a/drivers/video/wmt_ge_rops.c b/drivers/video/wmt_ge_rops.c
index 45832b7ef7d2..55be3865015b 100644
--- a/drivers/video/wmt_ge_rops.c
+++ b/drivers/video/wmt_ge_rops.c
@@ -167,18 +167,7 @@ static struct platform_driver wmt_ge_rops_driver = {
167 }, 167 },
168}; 168};
169 169
170static int __init wmt_ge_rops_init(void) 170module_platform_driver(wmt_ge_rops_driver);
171{
172 return platform_driver_register(&wmt_ge_rops_driver);
173}
174
175static void __exit wmt_ge_rops_exit(void)
176{
177 platform_driver_unregister(&wmt_ge_rops_driver);
178}
179
180module_init(wmt_ge_rops_init);
181module_exit(wmt_ge_rops_exit);
182 171
183MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com"); 172MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com");
184MODULE_DESCRIPTION("Accelerators for raster operations using " 173MODULE_DESCRIPTION("Accelerators for raster operations using "
diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c
index fcb6cd90f64d..18084525402a 100644
--- a/drivers/video/xilinxfb.c
+++ b/drivers/video/xilinxfb.c
@@ -511,25 +511,7 @@ static struct platform_driver xilinxfb_of_driver = {
511 }, 511 },
512}; 512};
513 513
514 514module_platform_driver(xilinxfb_of_driver);
515/* ---------------------------------------------------------------------
516 * Module setup and teardown
517 */
518
519static int __init
520xilinxfb_init(void)
521{
522 return platform_driver_register(&xilinxfb_of_driver);
523}
524
525static void __exit
526xilinxfb_cleanup(void)
527{
528 platform_driver_unregister(&xilinxfb_of_driver);
529}
530
531module_init(xilinxfb_init);
532module_exit(xilinxfb_cleanup);
533 515
534MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>"); 516MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
535MODULE_DESCRIPTION("Xilinx TFT frame buffer driver"); 517MODULE_DESCRIPTION("Xilinx TFT frame buffer driver");
diff --git a/include/linux/display.h b/include/linux/display.h
deleted file mode 100644
index 3bf70d639728..000000000000
--- a/include/linux/display.h
+++ /dev/null
@@ -1,61 +0,0 @@
1/*
2 * Copyright (C) 2006 James Simmons <jsimmons@infradead.org>
3 *
4 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or (at
9 * your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19 *
20 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21 */
22
23#ifndef _LINUX_DISPLAY_H
24#define _LINUX_DISPLAY_H
25
26#include <linux/device.h>
27
28struct display_device;
29
30/* This structure defines all the properties of a Display. */
31struct display_driver {
32 int (*set_contrast)(struct display_device *, unsigned int);
33 int (*get_contrast)(struct display_device *);
34 void (*suspend)(struct display_device *, pm_message_t state);
35 void (*resume)(struct display_device *);
36 int (*probe)(struct display_device *, void *);
37 int (*remove)(struct display_device *);
38 int max_contrast;
39};
40
41struct display_device {
42 struct module *owner; /* Owner module */
43 struct display_driver *driver;
44 struct device *parent; /* This is the parent */
45 struct device *dev; /* This is this display device */
46 struct mutex lock;
47 void *priv_data;
48 char type[16];
49 char *name;
50 int idx;
51};
52
53extern struct display_device *display_device_register(struct display_driver *driver,
54 struct device *dev, void *devdata);
55extern void display_device_unregister(struct display_device *dev);
56
57extern int probe_edid(struct display_device *dev, void *devdata);
58
59#define to_display_device(obj) container_of(obj, struct display_device, class_dev)
60
61#endif
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 1d6836c498dd..c18122f40543 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -45,6 +45,7 @@
45#define FB_TYPE_INTERLEAVED_PLANES 2 /* Interleaved planes */ 45#define FB_TYPE_INTERLEAVED_PLANES 2 /* Interleaved planes */
46#define FB_TYPE_TEXT 3 /* Text/attributes */ 46#define FB_TYPE_TEXT 3 /* Text/attributes */
47#define FB_TYPE_VGA_PLANES 4 /* EGA/VGA planes */ 47#define FB_TYPE_VGA_PLANES 4 /* EGA/VGA planes */
48#define FB_TYPE_FOURCC 5 /* Type identified by a V4L2 FOURCC */
48 49
49#define FB_AUX_TEXT_MDA 0 /* Monochrome text */ 50#define FB_AUX_TEXT_MDA 0 /* Monochrome text */
50#define FB_AUX_TEXT_CGA 1 /* CGA/EGA/VGA Color text */ 51#define FB_AUX_TEXT_CGA 1 /* CGA/EGA/VGA Color text */
@@ -69,6 +70,7 @@
69#define FB_VISUAL_PSEUDOCOLOR 3 /* Pseudo color (like atari) */ 70#define FB_VISUAL_PSEUDOCOLOR 3 /* Pseudo color (like atari) */
70#define FB_VISUAL_DIRECTCOLOR 4 /* Direct color */ 71#define FB_VISUAL_DIRECTCOLOR 4 /* Direct color */
71#define FB_VISUAL_STATIC_PSEUDOCOLOR 5 /* Pseudo color readonly */ 72#define FB_VISUAL_STATIC_PSEUDOCOLOR 5 /* Pseudo color readonly */
73#define FB_VISUAL_FOURCC 6 /* Visual identified by a V4L2 FOURCC */
72 74
73#define FB_ACCEL_NONE 0 /* no hardware accelerator */ 75#define FB_ACCEL_NONE 0 /* no hardware accelerator */
74#define FB_ACCEL_ATARIBLITT 1 /* Atari Blitter */ 76#define FB_ACCEL_ATARIBLITT 1 /* Atari Blitter */
@@ -154,6 +156,8 @@
154 156
155#define FB_ACCEL_PUV3_UNIGFX 0xa0 /* PKUnity-v3 Unigfx */ 157#define FB_ACCEL_PUV3_UNIGFX 0xa0 /* PKUnity-v3 Unigfx */
156 158
159#define FB_CAP_FOURCC 1 /* Device supports FOURCC-based formats */
160
157struct fb_fix_screeninfo { 161struct fb_fix_screeninfo {
158 char id[16]; /* identification string eg "TT Builtin" */ 162 char id[16]; /* identification string eg "TT Builtin" */
159 unsigned long smem_start; /* Start of frame buffer mem */ 163 unsigned long smem_start; /* Start of frame buffer mem */
@@ -171,7 +175,8 @@ struct fb_fix_screeninfo {
171 __u32 mmio_len; /* Length of Memory Mapped I/O */ 175 __u32 mmio_len; /* Length of Memory Mapped I/O */
172 __u32 accel; /* Indicate to driver which */ 176 __u32 accel; /* Indicate to driver which */
173 /* specific chip/card we have */ 177 /* specific chip/card we have */
174 __u16 reserved[3]; /* Reserved for future compatibility */ 178 __u16 capabilities; /* see FB_CAP_* */
179 __u16 reserved[2]; /* Reserved for future compatibility */
175}; 180};
176 181
177/* Interpretation of offset for color fields: All offsets are from the right, 182/* Interpretation of offset for color fields: All offsets are from the right,
@@ -246,8 +251,8 @@ struct fb_var_screeninfo {
246 __u32 yoffset; /* resolution */ 251 __u32 yoffset; /* resolution */
247 252
248 __u32 bits_per_pixel; /* guess what */ 253 __u32 bits_per_pixel; /* guess what */
249 __u32 grayscale; /* != 0 Graylevels instead of colors */ 254 __u32 grayscale; /* 0 = color, 1 = grayscale, */
250 255 /* >1 = FOURCC */
251 struct fb_bitfield red; /* bitfield in fb mem if true color, */ 256 struct fb_bitfield red; /* bitfield in fb mem if true color, */
252 struct fb_bitfield green; /* else only length is significant */ 257 struct fb_bitfield green; /* else only length is significant */
253 struct fb_bitfield blue; 258 struct fb_bitfield blue;
@@ -273,7 +278,8 @@ struct fb_var_screeninfo {
273 __u32 sync; /* see FB_SYNC_* */ 278 __u32 sync; /* see FB_SYNC_* */
274 __u32 vmode; /* see FB_VMODE_* */ 279 __u32 vmode; /* see FB_VMODE_* */
275 __u32 rotate; /* angle we rotate counter clockwise */ 280 __u32 rotate; /* angle we rotate counter clockwise */
276 __u32 reserved[5]; /* Reserved for future compatibility */ 281 __u32 colorspace; /* colorspace for FOURCC-based modes */
282 __u32 reserved[4]; /* Reserved for future compatibility */
277}; 283};
278 284
279struct fb_cmap { 285struct fb_cmap {
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 4b752d5ee80e..d2f74f8e3fe3 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -343,6 +343,8 @@ struct v4l2_pix_format {
343#define V4L2_PIX_FMT_NV21 v4l2_fourcc('N', 'V', '2', '1') /* 12 Y/CrCb 4:2:0 */ 343#define V4L2_PIX_FMT_NV21 v4l2_fourcc('N', 'V', '2', '1') /* 12 Y/CrCb 4:2:0 */
344#define V4L2_PIX_FMT_NV16 v4l2_fourcc('N', 'V', '1', '6') /* 16 Y/CbCr 4:2:2 */ 344#define V4L2_PIX_FMT_NV16 v4l2_fourcc('N', 'V', '1', '6') /* 16 Y/CbCr 4:2:2 */
345#define V4L2_PIX_FMT_NV61 v4l2_fourcc('N', 'V', '6', '1') /* 16 Y/CrCb 4:2:2 */ 345#define V4L2_PIX_FMT_NV61 v4l2_fourcc('N', 'V', '6', '1') /* 16 Y/CrCb 4:2:2 */
346#define V4L2_PIX_FMT_NV24 v4l2_fourcc('N', 'V', '2', '4') /* 24 Y/CbCr 4:4:4 */
347#define V4L2_PIX_FMT_NV42 v4l2_fourcc('N', 'V', '4', '2') /* 24 Y/CrCb 4:4:4 */
346 348
347/* two non contiguous planes - one Y, one Cr + Cb interleaved */ 349/* two non contiguous planes - one Y, one Cr + Cb interleaved */
348#define V4L2_PIX_FMT_NV12M v4l2_fourcc('N', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 */ 350#define V4L2_PIX_FMT_NV12M v4l2_fourcc('N', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 */
diff --git a/include/linux/zorro_ids.h b/include/linux/zorro_ids.h
index 7e749088910d..74bc53bcfdcf 100644
--- a/include/linux/zorro_ids.h
+++ b/include/linux/zorro_ids.h
@@ -360,8 +360,8 @@
360#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM ZORRO_ID(VILLAGE_TRONIC, 0x0B, 0) 360#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM ZORRO_ID(VILLAGE_TRONIC, 0x0B, 0)
361#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG ZORRO_ID(VILLAGE_TRONIC, 0x0C, 0) 361#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG ZORRO_ID(VILLAGE_TRONIC, 0x0C, 0)
362#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_SEGMENTED_MODE ZORRO_ID(VILLAGE_TRONIC, 0x0D, 0) 362#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_SEGMENTED_MODE ZORRO_ID(VILLAGE_TRONIC, 0x0D, 0)
363#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_MEM1 ZORRO_ID(VILLAGE_TRONIC, 0x15, 0) 363#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM1 ZORRO_ID(VILLAGE_TRONIC, 0x15, 0)
364#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_MEM2 ZORRO_ID(VILLAGE_TRONIC, 0x16, 0) 364#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM2 ZORRO_ID(VILLAGE_TRONIC, 0x16, 0)
365#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_REG ZORRO_ID(VILLAGE_TRONIC, 0x17, 0) 365#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_REG ZORRO_ID(VILLAGE_TRONIC, 0x17, 0)
366#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3 ZORRO_ID(VILLAGE_TRONIC, 0x18, 0) 366#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3 ZORRO_ID(VILLAGE_TRONIC, 0x18, 0)
367#define ZORRO_PROD_VILLAGE_TRONIC_ARIADNE ZORRO_ID(VILLAGE_TRONIC, 0xC9, 0) 367#define ZORRO_PROD_VILLAGE_TRONIC_ARIADNE ZORRO_ID(VILLAGE_TRONIC, 0xC9, 0)
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 378c7ed6760b..062b3b24ff10 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -200,6 +200,10 @@ enum omap_dss_clk_source {
200 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI, /* OMAP4: PLL2_CLK2 */ 200 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI, /* OMAP4: PLL2_CLK2 */
201}; 201};
202 202
203enum omap_hdmi_flags {
204 OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP = 1 << 0,
205};
206
203/* RFBI */ 207/* RFBI */
204 208
205struct rfbi_timings { 209struct rfbi_timings {
@@ -294,8 +298,8 @@ int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel,
294 u16 len); 298 u16 len);
295int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel); 299int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel);
296int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel); 300int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel);
297int dsi_video_mode_enable(struct omap_dss_device *dssdev, int channel); 301int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel);
298void dsi_video_mode_disable(struct omap_dss_device *dssdev, int channel); 302void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel);
299 303
300/* Board specific data */ 304/* Board specific data */
301struct omap_dss_board_info { 305struct omap_dss_board_info {
@@ -309,6 +313,8 @@ struct omap_dss_board_info {
309 313
310/* Init with the board info */ 314/* Init with the board info */
311extern int omap_display_init(struct omap_dss_board_info *board_data); 315extern int omap_display_init(struct omap_dss_board_info *board_data);
316/* HDMI mux init*/
317extern int omap_hdmi_init(enum omap_hdmi_flags flags);
312 318
313struct omap_display_platform_data { 319struct omap_display_platform_data {
314 struct omap_dss_board_info *board_data; 320 struct omap_dss_board_info *board_data;
@@ -352,8 +358,6 @@ struct omap_dss_cpr_coefs {
352}; 358};
353 359
354struct omap_overlay_info { 360struct omap_overlay_info {
355 bool enabled;
356
357 u32 paddr; 361 u32 paddr;
358 u32 p_uv_addr; /* for NV12 format */ 362 u32 p_uv_addr; /* for NV12 format */
359 u16 screen_width; 363 u16 screen_width;
@@ -385,11 +389,21 @@ struct omap_overlay {
385 389
386 /* dynamic fields */ 390 /* dynamic fields */
387 struct omap_overlay_manager *manager; 391 struct omap_overlay_manager *manager;
388 struct omap_overlay_info info;
389 392
390 bool manager_changed; 393 /*
391 /* if true, info has been changed, but not applied() yet */ 394 * The following functions do not block:
392 bool info_dirty; 395 *
396 * is_enabled
397 * set_overlay_info
398 * get_overlay_info
399 *
400 * The rest of the functions may block and cannot be called from
401 * interrupt context
402 */
403
404 int (*enable)(struct omap_overlay *ovl);
405 int (*disable)(struct omap_overlay *ovl);
406 bool (*is_enabled)(struct omap_overlay *ovl);
393 407
394 int (*set_manager)(struct omap_overlay *ovl, 408 int (*set_manager)(struct omap_overlay *ovl,
395 struct omap_overlay_manager *mgr); 409 struct omap_overlay_manager *mgr);
@@ -418,23 +432,27 @@ struct omap_overlay_manager_info {
418 432
419struct omap_overlay_manager { 433struct omap_overlay_manager {
420 struct kobject kobj; 434 struct kobject kobj;
421 struct list_head list;
422 435
423 /* static fields */ 436 /* static fields */
424 const char *name; 437 const char *name;
425 enum omap_channel id; 438 enum omap_channel id;
426 enum omap_overlay_manager_caps caps; 439 enum omap_overlay_manager_caps caps;
427 int num_overlays; 440 struct list_head overlays;
428 struct omap_overlay **overlays;
429 enum omap_display_type supported_displays; 441 enum omap_display_type supported_displays;
430 442
431 /* dynamic fields */ 443 /* dynamic fields */
432 struct omap_dss_device *device; 444 struct omap_dss_device *device;
433 struct omap_overlay_manager_info info;
434 445
435 bool device_changed; 446 /*
436 /* if true, info has been changed but not applied() yet */ 447 * The following functions do not block:
437 bool info_dirty; 448 *
449 * set_manager_info
450 * get_manager_info
451 * apply
452 *
453 * The rest of the functions may block and cannot be called from
454 * interrupt context
455 */
438 456
439 int (*set_device)(struct omap_overlay_manager *mgr, 457 int (*set_device)(struct omap_overlay_manager *mgr,
440 struct omap_dss_device *dssdev); 458 struct omap_dss_device *dssdev);
@@ -448,9 +466,6 @@ struct omap_overlay_manager {
448 int (*apply)(struct omap_overlay_manager *mgr); 466 int (*apply)(struct omap_overlay_manager *mgr);
449 int (*wait_for_go)(struct omap_overlay_manager *mgr); 467 int (*wait_for_go)(struct omap_overlay_manager *mgr);
450 int (*wait_for_vsync)(struct omap_overlay_manager *mgr); 468 int (*wait_for_vsync)(struct omap_overlay_manager *mgr);
451
452 int (*enable)(struct omap_overlay_manager *mgr);
453 int (*disable)(struct omap_overlay_manager *mgr);
454}; 469};
455 470
456struct omap_dss_device { 471struct omap_dss_device {
@@ -662,12 +677,7 @@ void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
662 bool enable); 677 bool enable);
663int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable); 678int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable);
664 679
665int omap_dsi_prepare_update(struct omap_dss_device *dssdev, 680int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
666 u16 *x, u16 *y, u16 *w, u16 *h,
667 bool enlarge_update_area);
668int omap_dsi_update(struct omap_dss_device *dssdev,
669 int channel,
670 u16 x, u16 y, u16 w, u16 h,
671 void (*callback)(int, void *), void *data); 681 void (*callback)(int, void *), void *data);
672int omap_dsi_request_vc(struct omap_dss_device *dssdev, int *channel); 682int omap_dsi_request_vc(struct omap_dss_device *dssdev, int *channel);
673int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id); 683int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id);
diff --git a/include/video/sh_mipi_dsi.h b/include/video/sh_mipi_dsi.h
index 6cb95c977de9..434d56b4a1a5 100644
--- a/include/video/sh_mipi_dsi.h
+++ b/include/video/sh_mipi_dsi.h
@@ -28,14 +28,33 @@ enum sh_mipi_dsi_data_fmt {
28struct sh_mobile_lcdc_chan_cfg; 28struct sh_mobile_lcdc_chan_cfg;
29 29
30#define SH_MIPI_DSI_HSABM (1 << 0) 30#define SH_MIPI_DSI_HSABM (1 << 0)
31#define SH_MIPI_DSI_HSPBM (1 << 1) 31#define SH_MIPI_DSI_HBPBM (1 << 1)
32#define SH_MIPI_DSI_HFPBM (1 << 2)
33#define SH_MIPI_DSI_BL2E (1 << 3)
34#define SH_MIPI_DSI_VSEE (1 << 4)
35#define SH_MIPI_DSI_HSEE (1 << 5)
36#define SH_MIPI_DSI_HSAE (1 << 6)
37
38#define SH_MIPI_DSI_HSbyteCLK (1 << 24)
39#define SH_MIPI_DSI_HS6divCLK (1 << 25)
40#define SH_MIPI_DSI_HS4divCLK (1 << 26)
41
42#define SH_MIPI_DSI_SYNC_PULSES_MODE (SH_MIPI_DSI_VSEE | \
43 SH_MIPI_DSI_HSEE | \
44 SH_MIPI_DSI_HSAE)
45#define SH_MIPI_DSI_SYNC_EVENTS_MODE (0)
46#define SH_MIPI_DSI_SYNC_BURST_MODE (SH_MIPI_DSI_BL2E)
32 47
33struct sh_mipi_dsi_info { 48struct sh_mipi_dsi_info {
34 enum sh_mipi_dsi_data_fmt data_format; 49 enum sh_mipi_dsi_data_fmt data_format;
35 struct sh_mobile_lcdc_chan_cfg *lcd_chan; 50 struct sh_mobile_lcdc_chan_cfg *lcd_chan;
51 int lane;
36 unsigned long flags; 52 unsigned long flags;
37 u32 clksrc; 53 u32 clksrc;
38 unsigned int vsynw_offset; 54 unsigned int vsynw_offset;
55 int (*set_dot_clock)(struct platform_device *pdev,
56 void __iomem *base,
57 int enable);
39}; 58};
40 59
41#endif 60#endif
diff --git a/include/video/sh_mobile_lcdc.h b/include/video/sh_mobile_lcdc.h
index 8101b726b48a..fe30b759c51e 100644
--- a/include/video/sh_mobile_lcdc.h
+++ b/include/video/sh_mobile_lcdc.h
@@ -174,7 +174,8 @@ struct sh_mobile_lcdc_bl_info {
174 174
175struct sh_mobile_lcdc_chan_cfg { 175struct sh_mobile_lcdc_chan_cfg {
176 int chan; 176 int chan;
177 int bpp; 177 int fourcc;
178 int colorspace;
178 int interface_type; /* selects RGBn or SYSn I/F, see above */ 179 int interface_type; /* selects RGBn or SYSn I/F, see above */
179 int clock_divider; 180 int clock_divider;
180 unsigned long flags; /* LCDC_FLAGS_... */ 181 unsigned long flags; /* LCDC_FLAGS_... */
@@ -184,7 +185,6 @@ struct sh_mobile_lcdc_chan_cfg {
184 struct sh_mobile_lcdc_board_cfg board_cfg; 185 struct sh_mobile_lcdc_board_cfg board_cfg;
185 struct sh_mobile_lcdc_bl_info bl_info; 186 struct sh_mobile_lcdc_bl_info bl_info;
186 struct sh_mobile_lcdc_sys_bus_cfg sys_bus_cfg; /* only for SYSn I/F */ 187 struct sh_mobile_lcdc_sys_bus_cfg sys_bus_cfg; /* only for SYSn I/F */
187 int nonstd;
188 struct sh_mobile_meram_cfg *meram_cfg; 188 struct sh_mobile_meram_cfg *meram_cfg;
189}; 189};
190 190