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

Merge branch 'fbdev-next' of git://github.com/schandinat/linux-2.6

* 'fbdev-next' of git://github.com/schandinat/linux-2.6: (175 commits)
module_param: make bool parameters really bool (drivers/video/i810)
Revert "atmel_lcdfb: Adjust HFP calculation so it matches the manual."
OMAPDSS: HDMI: Disable DDC internal pull up
OMAPDSS: HDMI: Move duplicate code from boardfile
OMAPDSS: add OrtusTech COM43H4M10XTC display support
OMAP: DSS2: Support for UMSH-8173MD TFT panel
ASoC: OMAP: HDMI: Move HDMI codec trigger function to generic HDMI driver
OMAPDSS: HDMI: Create function to enable HDMI audio
ASoC: OMAP: HDMI: Correct signature of ASoC functions
ASoC: OMAP: HDMI: Introduce driver data for audio codec
grvga: fix section mismatch warnings
video: s3c-fb: Don't keep device runtime active when open
video: s3c-fb: Hold runtime PM references when touching registers
video: s3c-fb: Take a runtime PM reference when unblanked
video: s3c-fb: Disable runtime PM in error paths from probe
video: s3c-fb: Use s3c_fb_enable() to enable the framebuffer
video: s3c-fb: Make runtime PM functional again
drivers/video: fsl-diu-fb: merge fsl_diu_alloc() into map_video_memory()
drivers/video: fsl-diu-fb: add default platform ops functions
drivers/video: fsl-diu-fb: remove broken reference count enabling the display
...

+6369 -5553
+121
Documentation/DocBook/media/v4l/pixfmt-nv24.xml
··· 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 10 + chroma resolutions, also known as YUV 4:4:4. One luminance and one 11 + chrominance 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 33 + pixel 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>
+1
Documentation/DocBook/media/v4l/pixfmt.xml
··· 714 714 &sub-nv12m; 715 715 &sub-nv12mt; 716 716 &sub-nv16; 717 + &sub-nv24; 717 718 &sub-m420; 718 719 </section> 719 720
+306
Documentation/fb/api.txt
··· 1 + The Frame Buffer Device API 2 + --------------------------- 3 + 4 + Last revised: June 21, 2011 5 + 6 + 7 + 0. Introduction 8 + --------------- 9 + 10 + This document describes the frame buffer API used by applications to interact 11 + with frame buffer devices. In-kernel APIs between device drivers and the frame 12 + buffer core are not described. 13 + 14 + Due to a lack of documentation in the original frame buffer API, drivers 15 + behaviours differ in subtle (and not so subtle) ways. This document describes 16 + the recommended API implementation, but applications should be prepared to 17 + deal with different behaviours. 18 + 19 + 20 + 1. Capabilities 21 + --------------- 22 + 23 + Device and driver capabilities are reported in the fixed screen information 24 + capabilities field. 25 + 26 + struct fb_fix_screeninfo { 27 + ... 28 + __u16 capabilities; /* see FB_CAP_* */ 29 + ... 30 + }; 31 + 32 + Application should use those capabilities to find out what features they can 33 + expect from the device and driver. 34 + 35 + - FB_CAP_FOURCC 36 + 37 + The driver supports the four character code (FOURCC) based format setting API. 38 + When supported, formats are configured using a FOURCC instead of manually 39 + specifying color components layout. 40 + 41 + 42 + 2. Types and visuals 43 + -------------------- 44 + 45 + Pixels are stored in memory in hardware-dependent formats. Applications need 46 + to be aware of the pixel storage format in order to write image data to the 47 + frame buffer memory in the format expected by the hardware. 48 + 49 + Formats are described by frame buffer types and visuals. Some visuals require 50 + additional information, which are stored in the variable screen information 51 + bits_per_pixel, grayscale, red, green, blue and transp fields. 52 + 53 + Visuals describe how color information is encoded and assembled to create 54 + macropixels. Types describe how macropixels are stored in memory. The following 55 + types and visuals are supported. 56 + 57 + - FB_TYPE_PACKED_PIXELS 58 + 59 + Macropixels are stored contiguously in a single plane. If the number of bits 60 + per macropixel is not a multiple of 8, whether macropixels are padded to the 61 + next multiple of 8 bits or packed together into bytes depends on the visual. 62 + 63 + Padding at end of lines may be present and is then reported through the fixed 64 + screen information line_length field. 65 + 66 + - FB_TYPE_PLANES 67 + 68 + Macropixels are split across multiple planes. The number of planes is equal to 69 + the number of bits per macropixel, with plane i'th storing i'th bit from all 70 + macropixels. 71 + 72 + Planes are located contiguously in memory. 73 + 74 + - FB_TYPE_INTERLEAVED_PLANES 75 + 76 + Macropixels are split across multiple planes. The number of planes is equal to 77 + the number of bits per macropixel, with plane i'th storing i'th bit from all 78 + macropixels. 79 + 80 + Planes are interleaved in memory. The interleave factor, defined as the 81 + distance in bytes between the beginning of two consecutive interleaved blocks 82 + belonging to different planes, is stored in the fixed screen information 83 + type_aux field. 84 + 85 + - FB_TYPE_FOURCC 86 + 87 + Macropixels are stored in memory as described by the format FOURCC identifier 88 + stored in the variable screen information grayscale field. 89 + 90 + - FB_VISUAL_MONO01 91 + 92 + Pixels are black or white and stored on a number of bits (typically one) 93 + specified by the variable screen information bpp field. 94 + 95 + Black pixels are represented by all bits set to 1 and white pixels by all bits 96 + set to 0. When the number of bits per pixel is smaller than 8, several pixels 97 + are packed together in a byte. 98 + 99 + FB_VISUAL_MONO01 is currently used with FB_TYPE_PACKED_PIXELS only. 100 + 101 + - FB_VISUAL_MONO10 102 + 103 + Pixels are black or white and stored on a number of bits (typically one) 104 + specified by the variable screen information bpp field. 105 + 106 + Black pixels are represented by all bits set to 0 and white pixels by all bits 107 + set to 1. When the number of bits per pixel is smaller than 8, several pixels 108 + are packed together in a byte. 109 + 110 + FB_VISUAL_MONO01 is currently used with FB_TYPE_PACKED_PIXELS only. 111 + 112 + - FB_VISUAL_TRUECOLOR 113 + 114 + Pixels are broken into red, green and blue components, and each component 115 + indexes a read-only lookup table for the corresponding value. Lookup tables 116 + are device-dependent, and provide linear or non-linear ramps. 117 + 118 + Each component is stored in a macropixel according to the variable screen 119 + information red, green, blue and transp fields. 120 + 121 + - FB_VISUAL_PSEUDOCOLOR and FB_VISUAL_STATIC_PSEUDOCOLOR 122 + 123 + Pixel values are encoded as indices into a colormap that stores red, green and 124 + blue components. The colormap is read-only for FB_VISUAL_STATIC_PSEUDOCOLOR 125 + and read-write for FB_VISUAL_PSEUDOCOLOR. 126 + 127 + Each pixel value is stored in the number of bits reported by the variable 128 + screen information bits_per_pixel field. 129 + 130 + - FB_VISUAL_DIRECTCOLOR 131 + 132 + Pixels are broken into red, green and blue components, and each component 133 + indexes a programmable lookup table for the corresponding value. 134 + 135 + Each component is stored in a macropixel according to the variable screen 136 + information red, green, blue and transp fields. 137 + 138 + - FB_VISUAL_FOURCC 139 + 140 + Pixels are encoded and interpreted as described by the format FOURCC 141 + identifier stored in the variable screen information grayscale field. 142 + 143 + 144 + 3. Screen information 145 + --------------------- 146 + 147 + Screen information are queried by applications using the FBIOGET_FSCREENINFO 148 + and FBIOGET_VSCREENINFO ioctls. Those ioctls take a pointer to a 149 + fb_fix_screeninfo and fb_var_screeninfo structure respectively. 150 + 151 + struct fb_fix_screeninfo stores device independent unchangeable information 152 + about the frame buffer device and the current format. Those information can't 153 + be directly modified by applications, but can be changed by the driver when an 154 + application modifies the format. 155 + 156 + struct 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 + 177 + struct fb_var_screeninfo stores device independent changeable information 178 + about a frame buffer device, its current format and video mode, as well as 179 + other miscellaneous parameters. 180 + 181 + struct 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 + 221 + To modify variable information, applications call the FBIOPUT_VSCREENINFO 222 + ioctl with a pointer to a fb_var_screeninfo structure. If the call is 223 + successful, the driver will update the fixed screen information accordingly. 224 + 225 + Instead of filling the complete fb_var_screeninfo structure manually, 226 + applications should call the FBIOGET_VSCREENINFO ioctl and modify only the 227 + fields they care about. 228 + 229 + 230 + 4. Format configuration 231 + ----------------------- 232 + 233 + Frame buffer devices offer two ways to configure the frame buffer format: the 234 + legacy API and the FOURCC-based API. 235 + 236 + 237 + The legacy API has been the only frame buffer format configuration API for a 238 + long time and is thus widely used by application. It is the recommended API 239 + for applications when using RGB and grayscale formats, as well as legacy 240 + non-standard formats. 241 + 242 + To select a format, applications set the fb_var_screeninfo bits_per_pixel field 243 + to the desired frame buffer depth. Values up to 8 will usually map to 244 + monochrome, 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 + 260 + struct 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 + 276 + Upon successful format configuration, drivers update the fb_fix_screeninfo 277 + type, visual and line_length fields depending on the selected format. 278 + 279 + 280 + The FOURCC-based API replaces format descriptions by four character codes 281 + (FOURCC). FOURCCs are abstract identifiers that uniquely define a format 282 + without explicitly describing it. This is the only API that supports YUV 283 + formats. Drivers are also encouraged to implement the FOURCC-based API for RGB 284 + and grayscale formats. 285 + 286 + Drivers that support the FOURCC-based API report this capability by setting 287 + the FB_CAP_FOURCC bit in the fb_fix_screeninfo capabilities field. 288 + 289 + FOURCC definitions are located in the linux/videodev2.h header. However, and 290 + despite starting with the V4L2_PIX_FMT_prefix, they are not restricted to V4L2 291 + and don't require usage of the V4L2 subsystem. FOURCC documentation is 292 + available in Documentation/DocBook/v4l/pixfmt.xml. 293 + 294 + To select a format, applications set the grayscale field to the desired FOURCC. 295 + For YUV formats, they should also select the appropriate colorspace by setting 296 + the colorspace field to one of the colorspaces listed in linux/videodev2.h and 297 + documented in Documentation/DocBook/v4l/colorspaces.xml. 298 + 299 + The red, green, blue and transp fields are not used with the FOURCC-based API. 300 + For forward compatibility reasons applications must zero those fields, and 301 + drivers must ignore them. Values other than 0 may get a meaning in future 302 + extensions. 303 + 304 + Upon successful format configuration, drivers update the fb_fix_screeninfo 305 + type, visual and line_length fields depending on the selected format. The type 306 + and visual fields are set to FB_TYPE_FOURCC and FB_VISUAL_FOURCC respectively.
+6
MAINTAINERS
··· 5669 5669 S: Supported 5670 5670 F: sound/soc/samsung 5671 5671 5672 + SAMSUNG FRAMEBUFFER DRIVER 5673 + M: Jingoo Han <jg1.han@samsung.com> 5674 + L: linux-fbdev@vger.kernel.org 5675 + S: Maintained 5676 + F: drivers/video/s3c-fb.c 5677 + 5672 5678 SERIAL DRIVERS 5673 5679 M: Alan Cox <alan@linux.intel.com> 5674 5680 L: linux-serial@vger.kernel.org
+8 -15
arch/arm/mach-omap2/board-4430sdp.c
··· 602 602 __func__, OMAP4_SFH7741_ENABLE_GPIO, error); 603 603 } 604 604 605 - static 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 - 619 605 static struct gpio sdp4430_hdmi_gpios[] = { 620 606 { HDMI_GPIO_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_hpd" }, 621 607 { HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" }, ··· 819 833 pr_err("%s: Could not get display_sel GPIO\n", __func__); 820 834 821 835 sdp4430_lcd_init(); 822 - sdp4430_hdmi_mux_init(); 823 836 sdp4430_picodlp_init(); 824 837 omap_display_init(&sdp4430_dss_data); 838 + /* 839 + * OMAP4460SDP/Blaze and OMAP4430 ES2.3 SDP/Blaze boards and 840 + * later have external pull up on the HDMI I2C lines 841 + */ 842 + if (cpu_is_omap446x() || omap_rev() > OMAP4430_REV_ES2_2) 843 + omap_hdmi_init(OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP); 844 + else 845 + omap_hdmi_init(0); 825 846 } 826 847 827 848 #ifdef CONFIG_OMAP_MUX
+9 -16
arch/arm/mach-omap2/board-omap4panda.c
··· 412 412 return r; 413 413 } 414 414 415 - 416 - static 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 - 430 415 static struct gpio panda_hdmi_gpios[] = { 431 416 { HDMI_GPIO_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_hpd" }, 432 417 { HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" }, ··· 463 478 if (r) 464 479 pr_err("error initializing panda DVI\n"); 465 480 466 - omap4_panda_hdmi_mux_init(); 467 481 omap_display_init(&omap4_panda_dss_data); 482 + 483 + /* 484 + * OMAP4460SDP/Blaze and OMAP4430 ES2.3 SDP/Blaze boards and 485 + * later have external pull up on the HDMI I2C lines 486 + */ 487 + if (cpu_is_omap446x() || omap_rev() > OMAP4430_REV_ES2_2) 488 + omap_hdmi_init(OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP); 489 + else 490 + omap_hdmi_init(0); 468 491 } 469 492 470 493 static void __init omap4_panda_init(void)
+39
arch/arm/mach-omap2/display.c
··· 30 30 #include <plat/omap-pm.h> 31 31 #include "common.h" 32 32 33 + #include "mux.h" 33 34 #include "control.h" 34 35 #include "display.h" 35 36 ··· 98 97 { "dss_hdmi", "omapdss_hdmi", -1 }, 99 98 }; 100 99 100 + static void omap4_hdmi_mux_pads(enum omap_hdmi_flags flags) 101 + { 102 + u32 reg; 103 + u16 control_i2c_1; 104 + 105 + /* PAD0_HDMI_HPD_PAD1_HDMI_CEC */ 106 + omap_mux_init_signal("hdmi_hpd", 107 + OMAP_PIN_INPUT_PULLUP); 108 + omap_mux_init_signal("hdmi_cec", 109 + OMAP_PIN_INPUT_PULLUP); 110 + /* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */ 111 + omap_mux_init_signal("hdmi_ddc_scl", 112 + OMAP_PIN_INPUT_PULLUP); 113 + omap_mux_init_signal("hdmi_ddc_sda", 114 + OMAP_PIN_INPUT_PULLUP); 115 + 116 + /* 117 + * CONTROL_I2C_1: HDMI_DDC_SDA_PULLUPRESX (bit 28) and 118 + * HDMI_DDC_SCL_PULLUPRESX (bit 24) are set to disable 119 + * internal pull up resistor. 120 + */ 121 + if (flags & OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP) { 122 + control_i2c_1 = OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_1; 123 + reg = omap4_ctrl_pad_readl(control_i2c_1); 124 + reg |= (OMAP4_HDMI_DDC_SDA_PULLUPRESX_MASK | 125 + OMAP4_HDMI_DDC_SCL_PULLUPRESX_MASK); 126 + omap4_ctrl_pad_writel(reg, control_i2c_1); 127 + } 128 + } 129 + 101 130 static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes) 102 131 { 103 132 u32 enable_mask, enable_shift; ··· 157 126 reg |= (lanes << pipd_shift) & pipd_mask; 158 127 159 128 omap4_ctrl_pad_writel(reg, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY); 129 + 130 + return 0; 131 + } 132 + 133 + int omap_hdmi_init(enum omap_hdmi_flags flags) 134 + { 135 + if (cpu_is_omap44xx()) 136 + omap4_hdmi_mux_pads(flags); 160 137 161 138 return 0; 162 139 }
+36 -7
arch/arm/mach-shmobile/board-ag5evm.c
··· 271 271 .flags = LCDC_FLAGS_DWPOL, 272 272 .lcd_size_cfg.width = 44, 273 273 .lcd_size_cfg.height = 79, 274 - .bpp = 16, 274 + .fourcc = V4L2_PIX_FMT_RGB565, 275 275 .lcd_cfg = lcdc0_modes, 276 276 .num_cfg = ARRAY_SIZE(lcdc0_modes), 277 277 .board_cfg = { ··· 321 321 }, 322 322 }; 323 323 324 + #define DSI0PHYCR 0xe615006c 325 + static 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 + 350 + sh_mipi_set_dot_clock_pck_err: 351 + return ret; 352 + } 353 + 324 354 static struct sh_mipi_dsi_info mipidsi0_info = { 325 355 .data_format = MIPI_RGB888, 326 356 .lcd_chan = &lcdc0_info.ch[0], 357 + .lane = 2, 327 358 .vsynw_offset = 20, 328 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 332 366 static struct platform_device mipidsi0_device = { ··· 506 472 shmobile_setup_console(); 507 473 } 508 474 509 - #define DSI0PHYCR 0xe615006c 510 - 511 475 static void __init ag5evm_init(void) 512 476 { 513 477 sh73a0_pinmux_init(); ··· 585 553 gpio_request(GPIO_PORT235, NULL); /* RESET */ 586 554 gpio_direction_output(GPIO_PORT235, 0); 587 555 lcd_backlight_reset(); 588 - 589 - /* MIPI-DSI clock setup */ 590 - __raw_writel(0x2a809010, DSI0PHYCR); 591 556 592 557 /* enable SDHI0 on CN15 [SD I/F] */ 593 558 gpio_request(GPIO_FN_SDHICD0, NULL);
+30 -2
arch/arm/mach-shmobile/board-ap4evb.c
··· 491 491 .meram_dev = &meram_info, 492 492 .ch[0] = { 493 493 .chan = LCDC_CHAN_MAINLCD, 494 - .bpp = 16, 494 + .fourcc = V4L2_PIX_FMT_RGB565, 495 495 .lcd_cfg = ap4evb_lcdc_modes, 496 496 .num_cfg = ARRAY_SIZE(ap4evb_lcdc_modes), 497 497 .meram_cfg = &lcd_meram_cfg, ··· 564 564 }; 565 565 566 566 /* MIPI-DSI */ 567 + #define PHYCTRL 0x0070 568 + static 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 + 567 591 static struct resource mipidsi0_resources[] = { 568 592 [0] = { 569 593 .start = 0xffc60000, ··· 604 580 static struct sh_mipi_dsi_info mipidsi0_info = { 605 581 .data_format = MIPI_RGB888, 606 582 .lcd_chan = &lcdc_info.ch[0], 583 + .lane = 2, 607 584 .vsynw_offset = 17, 585 + .flags = SH_MIPI_DSI_SYNC_PULSES_MODE | 586 + SH_MIPI_DSI_HSbyteCLK, 587 + .set_dot_clock = sh_mipi_set_dot_clock, 608 588 }; 609 589 610 590 static struct platform_device mipidsi0_device = { ··· 826 798 .meram_dev = &meram_info, 827 799 .ch[0] = { 828 800 .chan = LCDC_CHAN_MAINLCD, 829 - .bpp = 16, 801 + .fourcc = V4L2_PIX_FMT_RGB565, 830 802 .interface_type = RGB24, 831 803 .clock_divider = 1, 832 804 .flags = LCDC_FLAGS_DWPOL,
+2 -2
arch/arm/mach-shmobile/board-mackerel.c
··· 388 388 .clock_source = LCDC_CLK_BUS, 389 389 .ch[0] = { 390 390 .chan = LCDC_CHAN_MAINLCD, 391 - .bpp = 16, 391 + .fourcc = V4L2_PIX_FMT_RGB565, 392 392 .lcd_cfg = mackerel_lcdc_modes, 393 393 .num_cfg = ARRAY_SIZE(mackerel_lcdc_modes), 394 394 .interface_type = RGB24, ··· 451 451 .clock_source = LCDC_CLK_EXTERNAL, 452 452 .ch[0] = { 453 453 .chan = LCDC_CHAN_MAINLCD, 454 - .bpp = 16, 454 + .fourcc = V4L2_PIX_FMT_RGB565, 455 455 .interface_type = RGB24, 456 456 .clock_divider = 1, 457 457 .flags = LCDC_FLAGS_DWPOL,
+2 -2
arch/arm/mach-shmobile/clock-sh7372.c
··· 612 612 CLKDEV_CON_ID("hdmi_clk", &div6_reparent_clks[DIV6_HDMI]), 613 613 CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]), 614 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]), 616 - CLKDEV_ICK_ID("dsi1p_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]), 615 + CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]), 616 + CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]), 617 617 618 618 /* MSTP32 clocks */ 619 619 CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* IIC2 */
+2 -2
arch/arm/mach-shmobile/clock-sh73a0.c
··· 427 427 CLKDEV_CON_ID("sdhi2_clk", &div6_clks[DIV6_SDHI2]), 428 428 CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]), 429 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]), 431 - CLKDEV_ICK_ID("dsi1p_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]), 430 + CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]), 431 + CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]), 432 432 433 433 /* MSTP32 clocks */ 434 434 CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* I2C2 */
+1 -1
arch/sh/boards/mach-ap325rxa/setup.c
··· 207 207 .clock_source = LCDC_CLK_EXTERNAL, 208 208 .ch[0] = { 209 209 .chan = LCDC_CHAN_MAINLCD, 210 - .bpp = 16, 210 + .fourcc = V4L2_PIX_FMT_RGB565, 211 211 .interface_type = RGB18, 212 212 .clock_divider = 1, 213 213 .lcd_cfg = ap325rxa_lcdc_modes,
+1 -1
arch/sh/boards/mach-ecovec24/setup.c
··· 324 324 .ch[0] = { 325 325 .interface_type = RGB18, 326 326 .chan = LCDC_CHAN_MAINLCD, 327 - .bpp = 16, 327 + .fourcc = V4L2_PIX_FMT_RGB565, 328 328 .lcd_size_cfg = { /* 7.0 inch */ 329 329 .width = 152, 330 330 .height = 91,
+1 -1
arch/sh/boards/mach-kfr2r09/setup.c
··· 143 143 .clock_source = LCDC_CLK_BUS, 144 144 .ch[0] = { 145 145 .chan = LCDC_CHAN_MAINLCD, 146 - .bpp = 16, 146 + .fourcc = V4L2_PIX_FMT_RGB565, 147 147 .interface_type = SYS18, 148 148 .clock_divider = 6, 149 149 .flags = LCDC_FLAGS_DWPOL,
+2 -2
arch/sh/boards/mach-migor/setup.c
··· 241 241 .clock_source = LCDC_CLK_BUS, 242 242 .ch[0] = { 243 243 .chan = LCDC_CHAN_MAINLCD, 244 - .bpp = 16, 244 + .fourcc = V4L2_PIX_FMT_RGB565, 245 245 .interface_type = RGB16, 246 246 .clock_divider = 2, 247 247 .lcd_cfg = migor_lcd_modes, ··· 255 255 .clock_source = LCDC_CLK_PERIPHERAL, 256 256 .ch[0] = { 257 257 .chan = LCDC_CHAN_MAINLCD, 258 - .bpp = 16, 258 + .fourcc = V4L2_PIX_FMT_RGB565, 259 259 .interface_type = SYS16A, 260 260 .clock_divider = 10, 261 261 .lcd_cfg = migor_lcd_modes,
+1 -1
arch/sh/boards/mach-se/7724/setup.c
··· 179 179 .clock_source = LCDC_CLK_EXTERNAL, 180 180 .ch[0] = { 181 181 .chan = LCDC_CHAN_MAINLCD, 182 - .bpp = 16, 182 + .fourcc = V4L2_PIX_FMT_RGB565, 183 183 .clock_divider = 1, 184 184 .lcd_size_cfg = { /* 7.0 inch */ 185 185 .width = 152,
+15 -18
drivers/media/video/omap/omap_vout.c
··· 424 424 "%s enable=%d addr=%x width=%d\n height=%d color_mode=%d\n" 425 425 "rotation=%d mirror=%d posx=%d posy=%d out_width = %d \n" 426 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 428 info.color_mode, info.rotation, info.mirror, info.pos_x, 429 429 info.pos_y, info.out_width, info.out_height, info.rotation_type, 430 430 info.screen_width); ··· 943 943 /* Disable all the overlay managers connected with this interface */ 944 944 for (i = 0; i < ovid->num_overlays; i++) { 945 945 struct omap_overlay *ovl = ovid->overlays[i]; 946 - if (ovl->manager && ovl->manager->device) { 947 - struct omap_overlay_info info; 948 - ovl->get_overlay_info(ovl, &info); 949 - info.enabled = 0; 950 - ovl->set_overlay_info(ovl, &info); 951 - } 946 + if (ovl->manager && ovl->manager->device) 947 + ovl->disable(ovl); 952 948 } 953 949 /* Turn off the pipeline */ 954 950 ret = omapvid_apply_changes(vout); ··· 1664 1668 if (ovl->manager && ovl->manager->device) { 1665 1669 struct omap_overlay_info info; 1666 1670 ovl->get_overlay_info(ovl, &info); 1667 - info.enabled = 1; 1668 1671 info.paddr = addr; 1669 1672 if (ovl->set_overlay_info(ovl, &info)) { 1670 1673 ret = -EINVAL; ··· 1681 1686 ret = omapvid_apply_changes(vout); 1682 1687 if (ret) 1683 1688 v4l2_err(&vout->vid_dev->v4l2_dev, "failed to change mode\n"); 1689 + 1690 + for (j = 0; j < ovid->num_overlays; j++) { 1691 + struct omap_overlay *ovl = ovid->overlays[j]; 1692 + 1693 + if (ovl->manager && ovl->manager->device) { 1694 + ret = ovl->enable(ovl); 1695 + if (ret) 1696 + goto streamon_err1; 1697 + } 1698 + } 1684 1699 1685 1700 ret = 0; 1686 1701 ··· 1721 1716 for (j = 0; j < ovid->num_overlays; j++) { 1722 1717 struct omap_overlay *ovl = ovid->overlays[j]; 1723 1718 1724 - if (ovl->manager && ovl->manager->device) { 1725 - struct omap_overlay_info info; 1726 - 1727 - ovl->get_overlay_info(ovl, &info); 1728 - info.enabled = 0; 1729 - ret = ovl->set_overlay_info(ovl, &info); 1730 - if (ret) 1731 - v4l2_err(&vout->vid_dev->v4l2_dev, 1732 - "failed to update overlay info in streamoff\n"); 1733 - } 1719 + if (ovl->manager && ovl->manager->device) 1720 + ovl->disable(ovl); 1734 1721 } 1735 1722 1736 1723 /* Turn of the pipeline */
-1
drivers/video/Kconfig
··· 2413 2413 source "drivers/video/omap2/Kconfig" 2414 2414 2415 2415 source "drivers/video/backlight/Kconfig" 2416 - source "drivers/video/display/Kconfig" 2417 2416 2418 2417 if VT 2419 2418 source "drivers/video/console/Kconfig"
+1 -1
drivers/video/Makefile
··· 13 13 14 14 obj-$(CONFIG_VT) += console/ 15 15 obj-$(CONFIG_LOGO) += logo/ 16 - obj-y += backlight/ display/ 16 + obj-y += backlight/ 17 17 18 18 obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o 19 19 obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o
+1946 -1962
drivers/video/amifb.c
··· 152 152 153 153 - hsstrt: Start of horizontal synchronization pulse 154 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 156 - vsstrt: Start of vertical synchronization pulse 157 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 159 - hcenter: Start of vertical retrace for interlace 160 160 161 161 You can specify the blanking timings independently. Currently I just set ··· 184 184 clock): 185 185 186 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 188 - diwstrt_v: Vertical start of the visible window 189 189 - diwstop_v: Vertical stop of the visible window 190 190 - ddfstrt: Horizontal start of display DMA ··· 193 193 194 194 Sprite positioning: 195 195 196 - - sprstrt_h: Horizontal start-4 of sprite 196 + - sprstrt_h: Horizontal start - 4 of sprite 197 197 - sprstrt_v: Vertical start of sprite 198 198 199 199 (*) Even Commodore did it wrong in the AGA monitor drivers by not adding 1. ··· 212 212 display parameters. Here's what I found out: 213 213 214 214 - ddfstrt and ddfstop are best aligned to 64 pixels. 215 - - the chipset needs 64+4 horizontal pixels after the DMA start before the 216 - first pixel is output, so diwstrt_h = ddfstrt+64+4 if you want to 217 - display the first pixel on the line too. Increase diwstrt_h for virtual 218 - screen panning. 215 + - the chipset needs 64 + 4 horizontal pixels after the DMA start before 216 + the first pixel is output, so diwstrt_h = ddfstrt + 64 + 4 if you want 217 + to display the first pixel on the line too. Increase diwstrt_h for 218 + virtual screen panning. 219 219 - the display DMA always fetches 64 pixels at a time (fmode = 3). 220 - - ddfstop is ddfstrt+#pixels-64. 221 - - diwstop_h = diwstrt_h+xres+1. Because of the additional 1 this can be 1 222 - more than htotal. 220 + - ddfstop is ddfstrt+#pixels - 64. 221 + - diwstop_h = diwstrt_h + xres + 1. Because of the additional 1 this can 222 + be 1 more than htotal. 223 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 225 - `fall off' on the left. 224 + panning needs an extra 64 pixels on the left to prefetch the pixels that 225 + `fall off' on the left. 226 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 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 230 - I make diwstop_h and diwstop_v as large as possible. 231 231 232 232 General dependencies ··· 234 234 235 235 - all values are SHRES pixel (35ns) 236 236 237 - table 1:fetchstart table 2:prefetch table 3:fetchsize 238 - ------------------ ---------------- ----------------- 237 + table 1:fetchstart table 2:prefetch table 3:fetchsize 238 + ------------------ ---------------- ----------------- 239 239 Pixclock # SHRES|HIRES|LORES # SHRES|HIRES|LORES # SHRES|HIRES|LORES 240 240 -------------#------+-----+------#------+-----+------#------+-----+------ 241 241 Bus width 1x # 16 | 32 | 64 # 16 | 32 | 64 # 64 | 64 | 64 ··· 245 245 - chipset needs 4 pixels before the first pixel is output 246 246 - ddfstrt must be aligned to fetchstart (table 1) 247 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 249 - for horizontal panning decrease diwstrt_h 250 250 - the length of a fetchline must be aligned to fetchsize (table 3) 251 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) 253 - - ddfstop is ddfstrt+ddfsize-fetchsize 252 + moved to optimize use of dma (useful for OCS/ECS overscan displays) 253 + - ddfstop is ddfstrt + ddfsize - fetchsize 254 254 - If C= didn't change anything for AGA, then at following positions the 255 - dma bus is already used: 256 - ddfstrt < 48 -> memory refresh 257 - < 96 -> disk dma 258 - < 160 -> audio dma 259 - < 192 -> sprite 0 dma 260 - < 416 -> sprite dma (32 per sprite) 255 + dma bus is already used: 256 + ddfstrt < 48 -> memory refresh 257 + < 96 -> disk dma 258 + < 160 -> audio dma 259 + < 192 -> sprite 0 dma 260 + < 416 -> sprite dma (32 per sprite) 261 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 264 DMA priorities 265 265 -------------- ··· 269 269 the hardware cursor: 270 270 271 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 273 - if you want to go even further, you lose the hardware cursor too. 274 274 275 275 IMHO a hardware cursor is more important for X than horizontal scrolling, ··· 286 286 Standard VGA timings 287 287 -------------------- 288 288 289 - xres yres left right upper lower hsync vsync 290 - ---- ---- ---- ----- ----- ----- ----- ----- 289 + xres yres left right upper lower hsync vsync 290 + ---- ---- ---- ----- ----- ----- ----- ----- 291 291 80x25 720 400 27 45 35 12 108 2 292 292 80x30 720 480 27 45 30 9 108 2 293 293 ··· 297 297 298 298 As a comparison, graphics/monitor.h suggests the following: 299 299 300 - xres yres left right upper lower hsync vsync 301 - ---- ---- ---- ----- ----- ----- ----- ----- 300 + xres yres left right upper lower hsync vsync 301 + ---- ---- ---- ----- ----- ----- ----- ----- 302 302 303 303 VGA 640 480 52 112 24 19 112 - 2 + 304 304 VGA70 640 400 52 112 27 21 112 - 2 - ··· 309 309 310 310 VSYNC HSYNC Vertical size Vertical total 311 311 ----- ----- ------------- -------------- 312 - + + Reserved Reserved 313 - + - 400 414 314 - - + 350 362 315 - - - 480 496 312 + + + Reserved Reserved 313 + + - 400 414 314 + - + 350 362 315 + - - 480 496 316 316 317 317 Source: CL-GD542X Technical Reference Manual, Cirrus Logic, Oct 1992 318 318 ··· 326 326 ----------- 327 327 328 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 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 333 RETMA -> NTSC 334 334 ------------- 335 335 336 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 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 341 Thus if you want a PAL compatible display, you have to do the following: 342 342 343 343 - set the FB_SYNC_BROADCAST flag to indicate that standard broadcast 344 - timings are to be used. 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 347 - display. 348 - - make sure left_margin+xres+right_margin+hsync_len = 1816 for a SHRES, 349 - 908 for a HIRES and 454 for a LORES display. 344 + timings are to be used. 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 347 + display. 348 + - make sure left_margin + xres + right_margin + hsync_len = 1816 for a 349 + SHRES, 908 for a HIRES and 454 for a LORES display. 350 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 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 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 358 The settings for a NTSC compatible display are straightforward. 358 359 ··· 362 361 anything about horizontal/vertical synchronization nor refresh rates. 363 362 364 363 365 - -- Geert -- 364 + -- Geert -- 366 365 367 366 *******************************************************************************/ 368 367 ··· 541 540 * Various macros 542 541 */ 543 542 544 - #define up2(v) (((v)+1) & -2) 543 + #define up2(v) (((v) + 1) & -2) 545 544 #define down2(v) ((v) & -2) 546 545 #define div2(v) ((v)>>1) 547 546 #define mod2(v) ((v) & 1) 548 547 549 - #define up4(v) (((v)+3) & -4) 548 + #define up4(v) (((v) + 3) & -4) 550 549 #define down4(v) ((v) & -4) 551 - #define mul4(v) ((v)<<2) 550 + #define mul4(v) ((v) << 2) 552 551 #define div4(v) ((v)>>2) 553 552 #define mod4(v) ((v) & 3) 554 553 555 - #define up8(v) (((v)+7) & -8) 554 + #define up8(v) (((v) + 7) & -8) 556 555 #define down8(v) ((v) & -8) 557 556 #define div8(v) ((v)>>3) 558 557 #define mod8(v) ((v) & 7) 559 558 560 - #define up16(v) (((v)+15) & -16) 559 + #define up16(v) (((v) + 15) & -16) 561 560 #define down16(v) ((v) & -16) 562 561 #define div16(v) ((v)>>4) 563 562 #define mod16(v) ((v) & 15) 564 563 565 - #define up32(v) (((v)+31) & -32) 564 + #define up32(v) (((v) + 31) & -32) 566 565 #define down32(v) ((v) & -32) 567 566 #define div32(v) ((v)>>5) 568 567 #define mod32(v) ((v) & 31) 569 568 570 - #define up64(v) (((v)+63) & -64) 569 + #define up64(v) (((v) + 63) & -64) 571 570 #define down64(v) ((v) & -64) 572 571 #define div64(v) ((v)>>6) 573 572 #define mod64(v) ((v) & 63) 574 573 575 - #define upx(x,v) (((v)+(x)-1) & -(x)) 576 - #define downx(x,v) ((v) & -(x)) 577 - #define modx(x,v) ((v) & ((x)-1)) 574 + #define upx(x, v) (((v) + (x) - 1) & -(x)) 575 + #define downx(x, v) ((v) & -(x)) 576 + #define modx(x, v) ((v) & ((x) - 1)) 578 577 579 578 /* if x1 is not a constant, this macro won't make real sense :-) */ 580 579 #ifdef __mc68000__ 581 580 #define DIVUL(x1, x2) ({int res; asm("divul %1,%2,%3": "=d" (res): \ 582 - "d" (x2), "d" ((long)((x1)/0x100000000ULL)), "0" ((long)(x1))); res;}) 581 + "d" (x2), "d" ((long)((x1) / 0x100000000ULL)), "0" ((long)(x1))); res;}) 583 582 #else 584 583 /* We know a bit about the numbers, so we can do it this way */ 585 584 #define DIVUL(x1, x2) ((((long)((unsigned long long)x1 >> 8) / x2) << 8) + \ ··· 608 607 #define VIDEOMEMSIZE_ECS_1M (393216) /* ECS (1MB) : max 1024*768*16 */ 609 608 #define VIDEOMEMSIZE_OCS (262144) /* OCS : max ca. 800*600*16 */ 610 609 611 - #define SPRITEMEMSIZE (64*64/4) /* max 64*64*4 */ 610 + #define SPRITEMEMSIZE (64 * 64 / 4) /* max 64*64*4 */ 612 611 #define DUMMYSPRITEMEMSIZE (8) 613 612 static u_long spritememory; 614 613 ··· 635 634 * Copper Instructions 636 635 */ 637 636 638 - #define CMOVE(val, reg) (CUSTOM_OFS(reg)<<16 | (val)) 639 - #define CMOVE2(val, reg) ((CUSTOM_OFS(reg)+2)<<16 | (val)) 640 - #define CWAIT(x, y) (((y) & 0x1fe)<<23 | ((x) & 0x7f0)<<13 | 0x0001fffe) 637 + #define CMOVE(val, reg) (CUSTOM_OFS(reg) << 16 | (val)) 638 + #define CMOVE2(val, reg) ((CUSTOM_OFS(reg) + 2) << 16 | (val)) 639 + #define CWAIT(x, y) (((y) & 0x1fe) << 23 | ((x) & 0x7f0) << 13 | 0x0001fffe) 641 640 #define CEND (0xfffffffe) 642 641 643 642 ··· 710 709 * Current Video Mode 711 710 */ 712 711 713 - static struct amifb_par { 712 + struct amifb_par { 714 713 715 714 /* General Values */ 716 715 ··· 773 772 /* Additional AGA Hardware Registers */ 774 773 775 774 u_short fmode; /* vmode */ 776 - } currentpar; 777 - 778 - 779 - static struct fb_info fb_info = { 780 - .fix = { 781 - .id = "Amiga ", 782 - .visual = FB_VISUAL_PSEUDOCOLOR, 783 - .accel = FB_ACCEL_AMIGABLITT 784 - } 785 775 }; 786 776 787 777 ··· 812 820 813 821 static struct fb_videomode ami_modedb[] __initdata = { 814 822 815 - /* 816 - * AmigaOS Video Modes 817 - * 818 - * If you change these, make sure to update DEFMODE_* as well! 819 - */ 823 + /* 824 + * AmigaOS Video Modes 825 + * 826 + * If you change these, make sure to update DEFMODE_* as well! 827 + */ 820 828 821 - { 822 - /* 640x200, 15 kHz, 60 Hz (NTSC) */ 823 - "ntsc", 60, 640, 200, TAG_HIRES, 106, 86, 44, 16, 76, 2, 824 - FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 825 - }, { 826 - /* 640x400, 15 kHz, 60 Hz interlaced (NTSC) */ 827 - "ntsc-lace", 60, 640, 400, TAG_HIRES, 106, 86, 88, 33, 76, 4, 828 - FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 829 - }, { 830 - /* 640x256, 15 kHz, 50 Hz (PAL) */ 831 - "pal", 50, 640, 256, TAG_HIRES, 106, 86, 40, 14, 76, 2, 832 - FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 833 - }, { 834 - /* 640x512, 15 kHz, 50 Hz interlaced (PAL) */ 835 - "pal-lace", 50, 640, 512, TAG_HIRES, 106, 86, 80, 29, 76, 4, 836 - FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 837 - }, { 838 - /* 640x480, 29 kHz, 57 Hz */ 839 - "multiscan", 57, 640, 480, TAG_SHRES, 96, 112, 29, 8, 72, 8, 840 - 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 841 - }, { 842 - /* 640x960, 29 kHz, 57 Hz interlaced */ 843 - "multiscan-lace", 57, 640, 960, TAG_SHRES, 96, 112, 58, 16, 72, 16, 844 - 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 845 - }, { 846 - /* 640x200, 15 kHz, 72 Hz */ 847 - "euro36", 72, 640, 200, TAG_HIRES, 92, 124, 6, 6, 52, 5, 848 - 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 849 - }, { 850 - /* 640x400, 15 kHz, 72 Hz interlaced */ 851 - "euro36-lace", 72, 640, 400, TAG_HIRES, 92, 124, 12, 12, 52, 10, 852 - 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 853 - }, { 854 - /* 640x400, 29 kHz, 68 Hz */ 855 - "euro72", 68, 640, 400, TAG_SHRES, 164, 92, 9, 9, 80, 8, 856 - 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 857 - }, { 858 - /* 640x800, 29 kHz, 68 Hz interlaced */ 859 - "euro72-lace", 68, 640, 800, TAG_SHRES, 164, 92, 18, 18, 80, 16, 860 - 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 861 - }, { 862 - /* 800x300, 23 kHz, 70 Hz */ 863 - "super72", 70, 800, 300, TAG_SHRES, 212, 140, 10, 11, 80, 7, 864 - 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 865 - }, { 866 - /* 800x600, 23 kHz, 70 Hz interlaced */ 867 - "super72-lace", 70, 800, 600, TAG_SHRES, 212, 140, 20, 22, 80, 14, 868 - 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 869 - }, { 870 - /* 640x200, 27 kHz, 57 Hz doublescan */ 871 - "dblntsc", 57, 640, 200, TAG_SHRES, 196, 124, 18, 17, 80, 4, 872 - 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP 873 - }, { 874 - /* 640x400, 27 kHz, 57 Hz */ 875 - "dblntsc-ff", 57, 640, 400, TAG_SHRES, 196, 124, 36, 35, 80, 7, 876 - 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 877 - }, { 878 - /* 640x800, 27 kHz, 57 Hz interlaced */ 879 - "dblntsc-lace", 57, 640, 800, TAG_SHRES, 196, 124, 72, 70, 80, 14, 880 - 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 881 - }, { 882 - /* 640x256, 27 kHz, 47 Hz doublescan */ 883 - "dblpal", 47, 640, 256, TAG_SHRES, 196, 124, 14, 13, 80, 4, 884 - 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP 885 - }, { 886 - /* 640x512, 27 kHz, 47 Hz */ 887 - "dblpal-ff", 47, 640, 512, TAG_SHRES, 196, 124, 28, 27, 80, 7, 888 - 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 889 - }, { 890 - /* 640x1024, 27 kHz, 47 Hz interlaced */ 891 - "dblpal-lace", 47, 640, 1024, TAG_SHRES, 196, 124, 56, 54, 80, 14, 892 - 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 893 - }, 829 + { 830 + /* 640x200, 15 kHz, 60 Hz (NTSC) */ 831 + "ntsc", 60, 640, 200, TAG_HIRES, 106, 86, 44, 16, 76, 2, 832 + FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 833 + }, { 834 + /* 640x400, 15 kHz, 60 Hz interlaced (NTSC) */ 835 + "ntsc-lace", 60, 640, 400, TAG_HIRES, 106, 86, 88, 33, 76, 4, 836 + FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 837 + }, { 838 + /* 640x256, 15 kHz, 50 Hz (PAL) */ 839 + "pal", 50, 640, 256, TAG_HIRES, 106, 86, 40, 14, 76, 2, 840 + FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 841 + }, { 842 + /* 640x512, 15 kHz, 50 Hz interlaced (PAL) */ 843 + "pal-lace", 50, 640, 512, TAG_HIRES, 106, 86, 80, 29, 76, 4, 844 + FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 845 + }, { 846 + /* 640x480, 29 kHz, 57 Hz */ 847 + "multiscan", 57, 640, 480, TAG_SHRES, 96, 112, 29, 8, 72, 8, 848 + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 849 + }, { 850 + /* 640x960, 29 kHz, 57 Hz interlaced */ 851 + "multiscan-lace", 57, 640, 960, TAG_SHRES, 96, 112, 58, 16, 72, 852 + 16, 853 + 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 854 + }, { 855 + /* 640x200, 15 kHz, 72 Hz */ 856 + "euro36", 72, 640, 200, TAG_HIRES, 92, 124, 6, 6, 52, 5, 857 + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 858 + }, { 859 + /* 640x400, 15 kHz, 72 Hz interlaced */ 860 + "euro36-lace", 72, 640, 400, TAG_HIRES, 92, 124, 12, 12, 52, 861 + 10, 862 + 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 863 + }, { 864 + /* 640x400, 29 kHz, 68 Hz */ 865 + "euro72", 68, 640, 400, TAG_SHRES, 164, 92, 9, 9, 80, 8, 866 + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 867 + }, { 868 + /* 640x800, 29 kHz, 68 Hz interlaced */ 869 + "euro72-lace", 68, 640, 800, TAG_SHRES, 164, 92, 18, 18, 80, 870 + 16, 871 + 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 872 + }, { 873 + /* 800x300, 23 kHz, 70 Hz */ 874 + "super72", 70, 800, 300, TAG_SHRES, 212, 140, 10, 11, 80, 7, 875 + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 876 + }, { 877 + /* 800x600, 23 kHz, 70 Hz interlaced */ 878 + "super72-lace", 70, 800, 600, TAG_SHRES, 212, 140, 20, 22, 80, 879 + 14, 880 + 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 881 + }, { 882 + /* 640x200, 27 kHz, 57 Hz doublescan */ 883 + "dblntsc", 57, 640, 200, TAG_SHRES, 196, 124, 18, 17, 80, 4, 884 + 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP 885 + }, { 886 + /* 640x400, 27 kHz, 57 Hz */ 887 + "dblntsc-ff", 57, 640, 400, TAG_SHRES, 196, 124, 36, 35, 80, 7, 888 + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 889 + }, { 890 + /* 640x800, 27 kHz, 57 Hz interlaced */ 891 + "dblntsc-lace", 57, 640, 800, TAG_SHRES, 196, 124, 72, 70, 80, 892 + 14, 893 + 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 894 + }, { 895 + /* 640x256, 27 kHz, 47 Hz doublescan */ 896 + "dblpal", 47, 640, 256, TAG_SHRES, 196, 124, 14, 13, 80, 4, 897 + 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP 898 + }, { 899 + /* 640x512, 27 kHz, 47 Hz */ 900 + "dblpal-ff", 47, 640, 512, TAG_SHRES, 196, 124, 28, 27, 80, 7, 901 + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 902 + }, { 903 + /* 640x1024, 27 kHz, 47 Hz interlaced */ 904 + "dblpal-lace", 47, 640, 1024, TAG_SHRES, 196, 124, 56, 54, 80, 905 + 14, 906 + 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP 907 + }, 894 908 895 - /* 896 - * VGA Video Modes 897 - */ 909 + /* 910 + * VGA Video Modes 911 + */ 898 912 899 - { 900 - /* 640x480, 31 kHz, 60 Hz (VGA) */ 901 - "vga", 60, 640, 480, TAG_SHRES, 64, 96, 30, 9, 112, 2, 902 - 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 903 - }, { 904 - /* 640x400, 31 kHz, 70 Hz (VGA) */ 905 - "vga70", 70, 640, 400, TAG_SHRES, 64, 96, 35, 12, 112, 2, 906 - FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 907 - }, 913 + { 914 + /* 640x480, 31 kHz, 60 Hz (VGA) */ 915 + "vga", 60, 640, 480, TAG_SHRES, 64, 96, 30, 9, 112, 2, 916 + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 917 + }, { 918 + /* 640x400, 31 kHz, 70 Hz (VGA) */ 919 + "vga70", 70, 640, 400, TAG_SHRES, 64, 96, 35, 12, 112, 2, 920 + FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, 921 + FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 922 + }, 908 923 909 924 #if 0 910 925 911 - /* 912 - * A2024 video modes 913 - * These modes don't work yet because there's no A2024 driver. 914 - */ 926 + /* 927 + * A2024 video modes 928 + * These modes don't work yet because there's no A2024 driver. 929 + */ 915 930 916 - { 917 - /* 1024x800, 10 Hz */ 918 - "a2024-10", 10, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0, 919 - 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 920 - }, { 921 - /* 1024x800, 15 Hz */ 922 - "a2024-15", 15, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0, 923 - 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 924 - } 931 + { 932 + /* 1024x800, 10 Hz */ 933 + "a2024-10", 10, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0, 934 + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 935 + }, { 936 + /* 1024x800, 15 Hz */ 937 + "a2024-15", 15, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0, 938 + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP 939 + } 925 940 #endif 926 941 }; 927 942 ··· 951 952 952 953 static int amifb_ilbm = 0; /* interleaved or normal bitplanes */ 953 954 static int amifb_inverse = 0; 955 + 956 + static u32 amifb_hfmin __initdata; /* monitor hfreq lower limit (Hz) */ 957 + static u32 amifb_hfmax __initdata; /* monitor hfreq upper limit (Hz) */ 958 + static u16 amifb_vfmin __initdata; /* monitor vfreq lower limit (Hz) */ 959 + static u16 amifb_vfmax __initdata; /* monitor vfreq upper limit (Hz) */ 954 960 955 961 956 962 /* ··· 996 992 /* bplcon1 (smooth scrolling) */ 997 993 998 994 #define hscroll2hw(hscroll) \ 999 - (((hscroll)<<12 & 0x3000) | ((hscroll)<<8 & 0xc300) | \ 1000 - ((hscroll)<<4 & 0x0c00) | ((hscroll)<<2 & 0x00f0) | ((hscroll)>>2 & 0x000f)) 995 + (((hscroll) << 12 & 0x3000) | ((hscroll) << 8 & 0xc300) | \ 996 + ((hscroll) << 4 & 0x0c00) | ((hscroll) << 2 & 0x00f0) | \ 997 + ((hscroll)>>2 & 0x000f)) 1001 998 1002 999 /* diwstrt/diwstop/diwhigh (visible display window) */ 1003 1000 1004 1001 #define diwstrt2hw(diwstrt_h, diwstrt_v) \ 1005 - (((diwstrt_v)<<7 & 0xff00) | ((diwstrt_h)>>2 & 0x00ff)) 1002 + (((diwstrt_v) << 7 & 0xff00) | ((diwstrt_h)>>2 & 0x00ff)) 1006 1003 #define diwstop2hw(diwstop_h, diwstop_v) \ 1007 - (((diwstop_v)<<7 & 0xff00) | ((diwstop_h)>>2 & 0x00ff)) 1004 + (((diwstop_v) << 7 & 0xff00) | ((diwstop_h)>>2 & 0x00ff)) 1008 1005 #define diwhigh2hw(diwstrt_h, diwstrt_v, diwstop_h, diwstop_v) \ 1009 - (((diwstop_h)<<3 & 0x2000) | ((diwstop_h)<<11 & 0x1800) | \ 1006 + (((diwstop_h) << 3 & 0x2000) | ((diwstop_h) << 11 & 0x1800) | \ 1010 1007 ((diwstop_v)>>1 & 0x0700) | ((diwstrt_h)>>5 & 0x0020) | \ 1011 - ((diwstrt_h)<<3 & 0x0018) | ((diwstrt_v)>>9 & 0x0007)) 1008 + ((diwstrt_h) << 3 & 0x0018) | ((diwstrt_v)>>9 & 0x0007)) 1012 1009 1013 1010 /* ddfstrt/ddfstop (display DMA) */ 1014 1011 ··· 1020 1015 1021 1016 #define hsstrt2hw(hsstrt) (div8(hsstrt)) 1022 1017 #define hsstop2hw(hsstop) (div8(hsstop)) 1023 - #define htotal2hw(htotal) (div8(htotal)-1) 1018 + #define htotal2hw(htotal) (div8(htotal) - 1) 1024 1019 #define vsstrt2hw(vsstrt) (div2(vsstrt)) 1025 1020 #define vsstop2hw(vsstop) (div2(vsstop)) 1026 - #define vtotal2hw(vtotal) (div2(vtotal)-1) 1021 + #define vtotal2hw(vtotal) (div2(vtotal) - 1) 1027 1022 #define hcenter2hw(htotal) (div8(htotal)) 1028 1023 1029 1024 /* hbstrt/hbstop/vbstrt/vbstop (blanking timings) */ 1030 1025 1031 - #define hbstrt2hw(hbstrt) (((hbstrt)<<8 & 0x0700) | ((hbstrt)>>3 & 0x00ff)) 1032 - #define hbstop2hw(hbstop) (((hbstop)<<8 & 0x0700) | ((hbstop)>>3 & 0x00ff)) 1026 + #define hbstrt2hw(hbstrt) (((hbstrt) << 8 & 0x0700) | ((hbstrt)>>3 & 0x00ff)) 1027 + #define hbstop2hw(hbstop) (((hbstop) << 8 & 0x0700) | ((hbstop)>>3 & 0x00ff)) 1033 1028 #define vbstrt2hw(vbstrt) (div2(vbstrt)) 1034 1029 #define vbstop2hw(vbstop) (div2(vbstop)) 1035 1030 1036 1031 /* colour */ 1037 1032 1038 1033 #define rgb2hw8_high(red, green, blue) \ 1039 - (((red & 0xf0)<<4) | (green & 0xf0) | ((blue & 0xf0)>>4)) 1034 + (((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0)>>4)) 1040 1035 #define rgb2hw8_low(red, green, blue) \ 1041 - (((red & 0x0f)<<8) | ((green & 0x0f)<<4) | (blue & 0x0f)) 1036 + (((red & 0x0f) << 8) | ((green & 0x0f) << 4) | (blue & 0x0f)) 1042 1037 #define rgb2hw4(red, green, blue) \ 1043 - (((red & 0xf0)<<4) | (green & 0xf0) | ((blue & 0xf0)>>4)) 1038 + (((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0)>>4)) 1044 1039 #define rgb2hw2(red, green, blue) \ 1045 - (((red & 0xc0)<<4) | (green & 0xc0) | ((blue & 0xc0)>>4)) 1040 + (((red & 0xc0) << 4) | (green & 0xc0) | ((blue & 0xc0)>>4)) 1046 1041 1047 1042 /* sprpos/sprctl (sprite positioning) */ 1048 1043 1049 1044 #define spr2hw_pos(start_v, start_h) \ 1050 - (((start_v)<<7&0xff00) | ((start_h)>>3&0x00ff)) 1045 + (((start_v) << 7 & 0xff00) | ((start_h)>>3 & 0x00ff)) 1051 1046 #define spr2hw_ctl(start_v, start_h, stop_v) \ 1052 - (((stop_v)<<7&0xff00) | ((start_v)>>4&0x0040) | ((stop_v)>>5&0x0020) | \ 1053 - ((start_h)<<3&0x0018) | ((start_v)>>7&0x0004) | ((stop_v)>>8&0x0002) | \ 1054 - ((start_h)>>2&0x0001)) 1047 + (((stop_v) << 7 & 0xff00) | ((start_v)>>4 & 0x0040) | \ 1048 + ((stop_v)>>5 & 0x0020) | ((start_h) << 3 & 0x0018) | \ 1049 + ((start_v)>>7 & 0x0004) | ((stop_v)>>8 & 0x0002) | \ 1050 + ((start_h)>>2 & 0x0001)) 1055 1051 1056 1052 /* get current vertical position of beam */ 1057 1053 #define get_vbpos() ((u_short)((*(u_long volatile *)&custom.vposr >> 7) & 0xffe)) ··· 1061 1055 * Copper Initialisation List 1062 1056 */ 1063 1057 1064 - #define COPINITSIZE (sizeof(copins)*40) 1058 + #define COPINITSIZE (sizeof(copins) * 40) 1065 1059 1066 1060 enum { 1067 1061 cip_bplcon0 ··· 1072 1066 * Don't change the order, build_copper()/rebuild_copper() rely on this 1073 1067 */ 1074 1068 1075 - #define COPLISTSIZE (sizeof(copins)*64) 1069 + #define COPLISTSIZE (sizeof(copins) * 64) 1076 1070 1077 1071 enum { 1078 1072 cop_wait, cop_bplcon0, ··· 1114 1108 }; 1115 1109 1116 1110 1117 - /* 1118 - * Interface used by the world 1119 - */ 1120 - 1121 - int amifb_setup(char*); 1122 - 1123 - static int amifb_check_var(struct fb_var_screeninfo *var, 1124 - struct fb_info *info); 1125 - static int amifb_set_par(struct fb_info *info); 1126 - static int amifb_setcolreg(unsigned regno, unsigned red, unsigned green, 1127 - unsigned blue, unsigned transp, 1128 - struct fb_info *info); 1129 - static int amifb_blank(int blank, struct fb_info *info); 1130 - static int amifb_pan_display(struct fb_var_screeninfo *var, 1131 - struct fb_info *info); 1132 - static void amifb_fillrect(struct fb_info *info, 1133 - const struct fb_fillrect *rect); 1134 - static void amifb_copyarea(struct fb_info *info, 1135 - const struct fb_copyarea *region); 1136 - static void amifb_imageblit(struct fb_info *info, 1137 - const struct fb_image *image); 1138 - static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg); 1139 - 1140 - 1141 - /* 1142 - * Interface to the low level console driver 1143 - */ 1144 - 1145 - static void amifb_deinit(struct platform_device *pdev); 1146 - 1147 - /* 1148 - * Internal routines 1149 - */ 1150 - 1151 - static int flash_cursor(void); 1152 - static irqreturn_t amifb_interrupt(int irq, void *dev_id); 1153 - static u_long chipalloc(u_long size); 1154 - static void chipfree(void); 1155 - 1156 - /* 1157 - * Hardware routines 1158 - */ 1159 - 1160 - static int ami_decode_var(struct fb_var_screeninfo *var, 1161 - struct amifb_par *par); 1162 - static int ami_encode_var(struct fb_var_screeninfo *var, 1163 - struct amifb_par *par); 1164 - static void ami_pan_var(struct fb_var_screeninfo *var); 1165 - static int ami_update_par(void); 1166 - static void ami_update_display(void); 1167 - static void ami_init_display(void); 1168 - static void ami_do_blank(void); 1169 - static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix); 1170 - static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data); 1171 - static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data); 1172 - static int ami_get_cursorstate(struct fb_cursorstate *state); 1173 - static int ami_set_cursorstate(struct fb_cursorstate *state); 1174 - static void ami_set_sprite(void); 1175 - static void ami_init_copper(void); 1176 - static void ami_reinit_copper(void); 1177 - static void ami_build_copper(void); 1178 - static void ami_rebuild_copper(void); 1179 - 1180 - 1181 - static struct fb_ops amifb_ops = { 1182 - .owner = THIS_MODULE, 1183 - .fb_check_var = amifb_check_var, 1184 - .fb_set_par = amifb_set_par, 1185 - .fb_setcolreg = amifb_setcolreg, 1186 - .fb_blank = amifb_blank, 1187 - .fb_pan_display = amifb_pan_display, 1188 - .fb_fillrect = amifb_fillrect, 1189 - .fb_copyarea = amifb_copyarea, 1190 - .fb_imageblit = amifb_imageblit, 1191 - .fb_ioctl = amifb_ioctl, 1192 - }; 1193 - 1194 - static void __init amifb_setup_mcap(char *spec) 1195 - { 1196 - char *p; 1197 - int vmin, vmax, hmin, hmax; 1198 - 1199 - /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax> 1200 - * <V*> vertical freq. in Hz 1201 - * <H*> horizontal freq. in kHz 1202 - */ 1203 - 1204 - if (!(p = strsep(&spec, ";")) || !*p) 1205 - return; 1206 - vmin = simple_strtoul(p, NULL, 10); 1207 - if (vmin <= 0) 1208 - return; 1209 - if (!(p = strsep(&spec, ";")) || !*p) 1210 - return; 1211 - vmax = simple_strtoul(p, NULL, 10); 1212 - if (vmax <= 0 || vmax <= vmin) 1213 - return; 1214 - if (!(p = strsep(&spec, ";")) || !*p) 1215 - return; 1216 - hmin = 1000 * simple_strtoul(p, NULL, 10); 1217 - if (hmin <= 0) 1218 - return; 1219 - if (!(p = strsep(&spec, "")) || !*p) 1220 - return; 1221 - hmax = 1000 * simple_strtoul(p, NULL, 10); 1222 - if (hmax <= 0 || hmax <= hmin) 1223 - return; 1224 - 1225 - fb_info.monspecs.vfmin = vmin; 1226 - fb_info.monspecs.vfmax = vmax; 1227 - fb_info.monspecs.hfmin = hmin; 1228 - fb_info.monspecs.hfmax = hmax; 1229 - } 1230 - 1231 - int __init amifb_setup(char *options) 1232 - { 1233 - char *this_opt; 1234 - 1235 - if (!options || !*options) 1236 - return 0; 1237 - 1238 - while ((this_opt = strsep(&options, ",")) != NULL) { 1239 - if (!*this_opt) 1240 - continue; 1241 - if (!strcmp(this_opt, "inverse")) { 1242 - amifb_inverse = 1; 1243 - fb_invert_cmaps(); 1244 - } else if (!strcmp(this_opt, "ilbm")) 1245 - amifb_ilbm = 1; 1246 - else if (!strncmp(this_opt, "monitorcap:", 11)) 1247 - amifb_setup_mcap(this_opt+11); 1248 - else if (!strncmp(this_opt, "fstart:", 7)) 1249 - min_fstrt = simple_strtoul(this_opt+7, NULL, 0); 1250 - else 1251 - mode_option = this_opt; 1252 - } 1253 - 1254 - if (min_fstrt < 48) 1255 - min_fstrt = 48; 1256 - 1257 - return 0; 1258 - } 1259 - 1260 - 1261 - static int amifb_check_var(struct fb_var_screeninfo *var, 1262 - struct fb_info *info) 1263 - { 1264 - int err; 1265 - struct amifb_par par; 1266 - 1267 - /* Validate wanted screen parameters */ 1268 - if ((err = ami_decode_var(var, &par))) 1269 - return err; 1270 - 1271 - /* Encode (possibly rounded) screen parameters */ 1272 - ami_encode_var(var, &par); 1273 - return 0; 1274 - } 1275 - 1276 - 1277 - static int amifb_set_par(struct fb_info *info) 1278 - { 1279 - struct amifb_par *par = (struct amifb_par *)info->par; 1280 - 1281 - do_vmode_pan = 0; 1282 - do_vmode_full = 0; 1283 - 1284 - /* Decode wanted screen parameters */ 1285 - ami_decode_var(&info->var, par); 1286 - 1287 - /* Set new videomode */ 1288 - ami_build_copper(); 1289 - 1290 - /* Set VBlank trigger */ 1291 - do_vmode_full = 1; 1292 - 1293 - /* Update fix for new screen parameters */ 1294 - if (par->bpp == 1) { 1295 - info->fix.type = FB_TYPE_PACKED_PIXELS; 1296 - info->fix.type_aux = 0; 1297 - } else if (amifb_ilbm) { 1298 - info->fix.type = FB_TYPE_INTERLEAVED_PLANES; 1299 - info->fix.type_aux = par->next_line; 1300 - } else { 1301 - info->fix.type = FB_TYPE_PLANES; 1302 - info->fix.type_aux = 0; 1303 - } 1304 - info->fix.line_length = div8(upx(16<<maxfmode, par->vxres)); 1305 - 1306 - if (par->vmode & FB_VMODE_YWRAP) { 1307 - info->fix.ywrapstep = 1; 1308 - info->fix.xpanstep = 0; 1309 - info->fix.ypanstep = 0; 1310 - info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YWRAP | 1311 - FBINFO_READS_FAST; /* override SCROLL_REDRAW */ 1312 - } else { 1313 - info->fix.ywrapstep = 0; 1314 - if (par->vmode & FB_VMODE_SMOOTH_XPAN) 1315 - info->fix.xpanstep = 1; 1316 - else 1317 - info->fix.xpanstep = 16<<maxfmode; 1318 - info->fix.ypanstep = 1; 1319 - info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; 1320 - } 1321 - return 0; 1322 - } 1323 - 1324 - 1325 - /* 1326 - * Pan or Wrap the Display 1327 - * 1328 - * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag 1329 - */ 1330 - 1331 - static int amifb_pan_display(struct fb_var_screeninfo *var, 1332 - struct fb_info *info) 1333 - { 1334 - if (var->vmode & FB_VMODE_YWRAP) { 1335 - if (var->yoffset < 0 || 1336 - var->yoffset >= info->var.yres_virtual || var->xoffset) 1337 - return -EINVAL; 1338 - } else { 1339 - /* 1340 - * TODO: There will be problems when xpan!=1, so some columns 1341 - * on the right side will never be seen 1342 - */ 1343 - if (var->xoffset+info->var.xres > upx(16<<maxfmode, info->var.xres_virtual) || 1344 - var->yoffset+info->var.yres > info->var.yres_virtual) 1345 - return -EINVAL; 1346 - } 1347 - ami_pan_var(var); 1348 - info->var.xoffset = var->xoffset; 1349 - info->var.yoffset = var->yoffset; 1350 - if (var->vmode & FB_VMODE_YWRAP) 1351 - info->var.vmode |= FB_VMODE_YWRAP; 1352 - else 1353 - info->var.vmode &= ~FB_VMODE_YWRAP; 1354 - return 0; 1355 - } 1356 - 1357 - 1358 - #if BITS_PER_LONG == 32 1359 - #define BYTES_PER_LONG 4 1360 - #define SHIFT_PER_LONG 5 1361 - #elif BITS_PER_LONG == 64 1362 - #define BYTES_PER_LONG 8 1363 - #define SHIFT_PER_LONG 6 1364 - #else 1365 - #define Please update me 1366 - #endif 1367 - 1368 - 1369 - /* 1370 - * Compose two values, using a bitmask as decision value 1371 - * This is equivalent to (a & mask) | (b & ~mask) 1372 - */ 1373 - 1374 - static inline unsigned long comp(unsigned long a, unsigned long b, 1375 - unsigned long mask) 1376 - { 1377 - return ((a ^ b) & mask) ^ b; 1378 - } 1379 - 1380 - 1381 - static inline unsigned long xor(unsigned long a, unsigned long b, 1382 - unsigned long mask) 1383 - { 1384 - return (a & mask) ^ b; 1385 - } 1386 - 1387 - 1388 - /* 1389 - * Unaligned forward bit copy using 32-bit or 64-bit memory accesses 1390 - */ 1391 - 1392 - static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src, 1393 - int src_idx, u32 n) 1394 - { 1395 - unsigned long first, last; 1396 - int shift = dst_idx-src_idx, left, right; 1397 - unsigned long d0, d1; 1398 - int m; 1399 - 1400 - if (!n) 1401 - return; 1402 - 1403 - shift = dst_idx-src_idx; 1404 - first = ~0UL >> dst_idx; 1405 - last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG)); 1406 - 1407 - if (!shift) { 1408 - // Same alignment for source and dest 1409 - 1410 - if (dst_idx+n <= BITS_PER_LONG) { 1411 - // Single word 1412 - if (last) 1413 - first &= last; 1414 - *dst = comp(*src, *dst, first); 1415 - } else { 1416 - // Multiple destination words 1417 - // Leading bits 1418 - if (first) { 1419 - *dst = comp(*src, *dst, first); 1420 - dst++; 1421 - src++; 1422 - n -= BITS_PER_LONG-dst_idx; 1423 - } 1424 - 1425 - // Main chunk 1426 - n /= BITS_PER_LONG; 1427 - while (n >= 8) { 1428 - *dst++ = *src++; 1429 - *dst++ = *src++; 1430 - *dst++ = *src++; 1431 - *dst++ = *src++; 1432 - *dst++ = *src++; 1433 - *dst++ = *src++; 1434 - *dst++ = *src++; 1435 - *dst++ = *src++; 1436 - n -= 8; 1437 - } 1438 - while (n--) 1439 - *dst++ = *src++; 1440 - 1441 - // Trailing bits 1442 - if (last) 1443 - *dst = comp(*src, *dst, last); 1444 - } 1445 - } else { 1446 - // Different alignment for source and dest 1447 - 1448 - right = shift & (BITS_PER_LONG-1); 1449 - left = -shift & (BITS_PER_LONG-1); 1450 - 1451 - if (dst_idx+n <= BITS_PER_LONG) { 1452 - // Single destination word 1453 - if (last) 1454 - first &= last; 1455 - if (shift > 0) { 1456 - // Single source word 1457 - *dst = comp(*src >> right, *dst, first); 1458 - } else if (src_idx+n <= BITS_PER_LONG) { 1459 - // Single source word 1460 - *dst = comp(*src << left, *dst, first); 1461 - } else { 1462 - // 2 source words 1463 - d0 = *src++; 1464 - d1 = *src; 1465 - *dst = comp(d0 << left | d1 >> right, *dst, 1466 - first); 1467 - } 1468 - } else { 1469 - // Multiple destination words 1470 - d0 = *src++; 1471 - // Leading bits 1472 - if (shift > 0) { 1473 - // Single source word 1474 - *dst = comp(d0 >> right, *dst, first); 1475 - dst++; 1476 - n -= BITS_PER_LONG-dst_idx; 1477 - } else { 1478 - // 2 source words 1479 - d1 = *src++; 1480 - *dst = comp(d0 << left | d1 >> right, *dst, 1481 - first); 1482 - d0 = d1; 1483 - dst++; 1484 - n -= BITS_PER_LONG-dst_idx; 1485 - } 1486 - 1487 - // Main chunk 1488 - m = n % BITS_PER_LONG; 1489 - n /= BITS_PER_LONG; 1490 - while (n >= 4) { 1491 - d1 = *src++; 1492 - *dst++ = d0 << left | d1 >> right; 1493 - d0 = d1; 1494 - d1 = *src++; 1495 - *dst++ = d0 << left | d1 >> right; 1496 - d0 = d1; 1497 - d1 = *src++; 1498 - *dst++ = d0 << left | d1 >> right; 1499 - d0 = d1; 1500 - d1 = *src++; 1501 - *dst++ = d0 << left | d1 >> right; 1502 - d0 = d1; 1503 - n -= 4; 1504 - } 1505 - while (n--) { 1506 - d1 = *src++; 1507 - *dst++ = d0 << left | d1 >> right; 1508 - d0 = d1; 1509 - } 1510 - 1511 - // Trailing bits 1512 - if (last) { 1513 - if (m <= right) { 1514 - // Single source word 1515 - *dst = comp(d0 << left, *dst, last); 1516 - } else { 1517 - // 2 source words 1518 - d1 = *src; 1519 - *dst = comp(d0 << left | d1 >> right, 1520 - *dst, last); 1521 - } 1522 - } 1523 - } 1524 - } 1525 - } 1526 - 1527 - 1528 - /* 1529 - * Unaligned reverse bit copy using 32-bit or 64-bit memory accesses 1530 - */ 1531 - 1532 - static void bitcpy_rev(unsigned long *dst, int dst_idx, 1533 - const unsigned long *src, int src_idx, u32 n) 1534 - { 1535 - unsigned long first, last; 1536 - int shift = dst_idx-src_idx, left, right; 1537 - unsigned long d0, d1; 1538 - int m; 1539 - 1540 - if (!n) 1541 - return; 1542 - 1543 - dst += (n-1)/BITS_PER_LONG; 1544 - src += (n-1)/BITS_PER_LONG; 1545 - if ((n-1) % BITS_PER_LONG) { 1546 - dst_idx += (n-1) % BITS_PER_LONG; 1547 - dst += dst_idx >> SHIFT_PER_LONG; 1548 - dst_idx &= BITS_PER_LONG-1; 1549 - src_idx += (n-1) % BITS_PER_LONG; 1550 - src += src_idx >> SHIFT_PER_LONG; 1551 - src_idx &= BITS_PER_LONG-1; 1552 - } 1553 - 1554 - shift = dst_idx-src_idx; 1555 - first = ~0UL << (BITS_PER_LONG-1-dst_idx); 1556 - last = ~(~0UL << (BITS_PER_LONG-1-((dst_idx-n) % BITS_PER_LONG))); 1557 - 1558 - if (!shift) { 1559 - // Same alignment for source and dest 1560 - 1561 - if ((unsigned long)dst_idx+1 >= n) { 1562 - // Single word 1563 - if (last) 1564 - first &= last; 1565 - *dst = comp(*src, *dst, first); 1566 - } else { 1567 - // Multiple destination words 1568 - // Leading bits 1569 - if (first) { 1570 - *dst = comp(*src, *dst, first); 1571 - dst--; 1572 - src--; 1573 - n -= dst_idx+1; 1574 - } 1575 - 1576 - // Main chunk 1577 - n /= BITS_PER_LONG; 1578 - while (n >= 8) { 1579 - *dst-- = *src--; 1580 - *dst-- = *src--; 1581 - *dst-- = *src--; 1582 - *dst-- = *src--; 1583 - *dst-- = *src--; 1584 - *dst-- = *src--; 1585 - *dst-- = *src--; 1586 - *dst-- = *src--; 1587 - n -= 8; 1588 - } 1589 - while (n--) 1590 - *dst-- = *src--; 1591 - 1592 - // Trailing bits 1593 - if (last) 1594 - *dst = comp(*src, *dst, last); 1595 - } 1596 - } else { 1597 - // Different alignment for source and dest 1598 - 1599 - right = shift & (BITS_PER_LONG-1); 1600 - left = -shift & (BITS_PER_LONG-1); 1601 - 1602 - if ((unsigned long)dst_idx+1 >= n) { 1603 - // Single destination word 1604 - if (last) 1605 - first &= last; 1606 - if (shift < 0) { 1607 - // Single source word 1608 - *dst = comp(*src << left, *dst, first); 1609 - } else if (1+(unsigned long)src_idx >= n) { 1610 - // Single source word 1611 - *dst = comp(*src >> right, *dst, first); 1612 - } else { 1613 - // 2 source words 1614 - d0 = *src--; 1615 - d1 = *src; 1616 - *dst = comp(d0 >> right | d1 << left, *dst, 1617 - first); 1618 - } 1619 - } else { 1620 - // Multiple destination words 1621 - d0 = *src--; 1622 - // Leading bits 1623 - if (shift < 0) { 1624 - // Single source word 1625 - *dst = comp(d0 << left, *dst, first); 1626 - dst--; 1627 - n -= dst_idx+1; 1628 - } else { 1629 - // 2 source words 1630 - d1 = *src--; 1631 - *dst = comp(d0 >> right | d1 << left, *dst, 1632 - first); 1633 - d0 = d1; 1634 - dst--; 1635 - n -= dst_idx+1; 1636 - } 1637 - 1638 - // Main chunk 1639 - m = n % BITS_PER_LONG; 1640 - n /= BITS_PER_LONG; 1641 - while (n >= 4) { 1642 - d1 = *src--; 1643 - *dst-- = d0 >> right | d1 << left; 1644 - d0 = d1; 1645 - d1 = *src--; 1646 - *dst-- = d0 >> right | d1 << left; 1647 - d0 = d1; 1648 - d1 = *src--; 1649 - *dst-- = d0 >> right | d1 << left; 1650 - d0 = d1; 1651 - d1 = *src--; 1652 - *dst-- = d0 >> right | d1 << left; 1653 - d0 = d1; 1654 - n -= 4; 1655 - } 1656 - while (n--) { 1657 - d1 = *src--; 1658 - *dst-- = d0 >> right | d1 << left; 1659 - d0 = d1; 1660 - } 1661 - 1662 - // Trailing bits 1663 - if (last) { 1664 - if (m <= left) { 1665 - // Single source word 1666 - *dst = comp(d0 >> right, *dst, last); 1667 - } else { 1668 - // 2 source words 1669 - d1 = *src; 1670 - *dst = comp(d0 >> right | d1 << left, 1671 - *dst, last); 1672 - } 1673 - } 1674 - } 1675 - } 1676 - } 1677 - 1678 - 1679 - /* 1680 - * Unaligned forward inverting bit copy using 32-bit or 64-bit memory 1681 - * accesses 1682 - */ 1683 - 1684 - static void bitcpy_not(unsigned long *dst, int dst_idx, 1685 - const unsigned long *src, int src_idx, u32 n) 1686 - { 1687 - unsigned long first, last; 1688 - int shift = dst_idx-src_idx, left, right; 1689 - unsigned long d0, d1; 1690 - int m; 1691 - 1692 - if (!n) 1693 - return; 1694 - 1695 - shift = dst_idx-src_idx; 1696 - first = ~0UL >> dst_idx; 1697 - last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG)); 1698 - 1699 - if (!shift) { 1700 - // Same alignment for source and dest 1701 - 1702 - if (dst_idx+n <= BITS_PER_LONG) { 1703 - // Single word 1704 - if (last) 1705 - first &= last; 1706 - *dst = comp(~*src, *dst, first); 1707 - } else { 1708 - // Multiple destination words 1709 - // Leading bits 1710 - if (first) { 1711 - *dst = comp(~*src, *dst, first); 1712 - dst++; 1713 - src++; 1714 - n -= BITS_PER_LONG-dst_idx; 1715 - } 1716 - 1717 - // Main chunk 1718 - n /= BITS_PER_LONG; 1719 - while (n >= 8) { 1720 - *dst++ = ~*src++; 1721 - *dst++ = ~*src++; 1722 - *dst++ = ~*src++; 1723 - *dst++ = ~*src++; 1724 - *dst++ = ~*src++; 1725 - *dst++ = ~*src++; 1726 - *dst++ = ~*src++; 1727 - *dst++ = ~*src++; 1728 - n -= 8; 1729 - } 1730 - while (n--) 1731 - *dst++ = ~*src++; 1732 - 1733 - // Trailing bits 1734 - if (last) 1735 - *dst = comp(~*src, *dst, last); 1736 - } 1737 - } else { 1738 - // Different alignment for source and dest 1739 - 1740 - right = shift & (BITS_PER_LONG-1); 1741 - left = -shift & (BITS_PER_LONG-1); 1742 - 1743 - if (dst_idx+n <= BITS_PER_LONG) { 1744 - // Single destination word 1745 - if (last) 1746 - first &= last; 1747 - if (shift > 0) { 1748 - // Single source word 1749 - *dst = comp(~*src >> right, *dst, first); 1750 - } else if (src_idx+n <= BITS_PER_LONG) { 1751 - // Single source word 1752 - *dst = comp(~*src << left, *dst, first); 1753 - } else { 1754 - // 2 source words 1755 - d0 = ~*src++; 1756 - d1 = ~*src; 1757 - *dst = comp(d0 << left | d1 >> right, *dst, 1758 - first); 1759 - } 1760 - } else { 1761 - // Multiple destination words 1762 - d0 = ~*src++; 1763 - // Leading bits 1764 - if (shift > 0) { 1765 - // Single source word 1766 - *dst = comp(d0 >> right, *dst, first); 1767 - dst++; 1768 - n -= BITS_PER_LONG-dst_idx; 1769 - } else { 1770 - // 2 source words 1771 - d1 = ~*src++; 1772 - *dst = comp(d0 << left | d1 >> right, *dst, 1773 - first); 1774 - d0 = d1; 1775 - dst++; 1776 - n -= BITS_PER_LONG-dst_idx; 1777 - } 1778 - 1779 - // Main chunk 1780 - m = n % BITS_PER_LONG; 1781 - n /= BITS_PER_LONG; 1782 - while (n >= 4) { 1783 - d1 = ~*src++; 1784 - *dst++ = d0 << left | d1 >> right; 1785 - d0 = d1; 1786 - d1 = ~*src++; 1787 - *dst++ = d0 << left | d1 >> right; 1788 - d0 = d1; 1789 - d1 = ~*src++; 1790 - *dst++ = d0 << left | d1 >> right; 1791 - d0 = d1; 1792 - d1 = ~*src++; 1793 - *dst++ = d0 << left | d1 >> right; 1794 - d0 = d1; 1795 - n -= 4; 1796 - } 1797 - while (n--) { 1798 - d1 = ~*src++; 1799 - *dst++ = d0 << left | d1 >> right; 1800 - d0 = d1; 1801 - } 1802 - 1803 - // Trailing bits 1804 - if (last) { 1805 - if (m <= right) { 1806 - // Single source word 1807 - *dst = comp(d0 << left, *dst, last); 1808 - } else { 1809 - // 2 source words 1810 - d1 = ~*src; 1811 - *dst = comp(d0 << left | d1 >> right, 1812 - *dst, last); 1813 - } 1814 - } 1815 - } 1816 - } 1817 - } 1818 - 1819 - 1820 - /* 1821 - * Unaligned 32-bit pattern fill using 32/64-bit memory accesses 1822 - */ 1823 - 1824 - static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n) 1825 - { 1826 - unsigned long val = pat; 1827 - unsigned long first, last; 1828 - 1829 - if (!n) 1830 - return; 1831 - 1832 - #if BITS_PER_LONG == 64 1833 - val |= val << 32; 1834 - #endif 1835 - 1836 - first = ~0UL >> dst_idx; 1837 - last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG)); 1838 - 1839 - if (dst_idx+n <= BITS_PER_LONG) { 1840 - // Single word 1841 - if (last) 1842 - first &= last; 1843 - *dst = comp(val, *dst, first); 1844 - } else { 1845 - // Multiple destination words 1846 - // Leading bits 1847 - if (first) { 1848 - *dst = comp(val, *dst, first); 1849 - dst++; 1850 - n -= BITS_PER_LONG-dst_idx; 1851 - } 1852 - 1853 - // Main chunk 1854 - n /= BITS_PER_LONG; 1855 - while (n >= 8) { 1856 - *dst++ = val; 1857 - *dst++ = val; 1858 - *dst++ = val; 1859 - *dst++ = val; 1860 - *dst++ = val; 1861 - *dst++ = val; 1862 - *dst++ = val; 1863 - *dst++ = val; 1864 - n -= 8; 1865 - } 1866 - while (n--) 1867 - *dst++ = val; 1868 - 1869 - // Trailing bits 1870 - if (last) 1871 - *dst = comp(val, *dst, last); 1872 - } 1873 - } 1874 - 1875 - 1876 - /* 1877 - * Unaligned 32-bit pattern xor using 32/64-bit memory accesses 1878 - */ 1879 - 1880 - static void bitxor32(unsigned long *dst, int dst_idx, u32 pat, u32 n) 1881 - { 1882 - unsigned long val = pat; 1883 - unsigned long first, last; 1884 - 1885 - if (!n) 1886 - return; 1887 - 1888 - #if BITS_PER_LONG == 64 1889 - val |= val << 32; 1890 - #endif 1891 - 1892 - first = ~0UL >> dst_idx; 1893 - last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG)); 1894 - 1895 - if (dst_idx+n <= BITS_PER_LONG) { 1896 - // Single word 1897 - if (last) 1898 - first &= last; 1899 - *dst = xor(val, *dst, first); 1900 - } else { 1901 - // Multiple destination words 1902 - // Leading bits 1903 - if (first) { 1904 - *dst = xor(val, *dst, first); 1905 - dst++; 1906 - n -= BITS_PER_LONG-dst_idx; 1907 - } 1908 - 1909 - // Main chunk 1910 - n /= BITS_PER_LONG; 1911 - while (n >= 4) { 1912 - *dst++ ^= val; 1913 - *dst++ ^= val; 1914 - *dst++ ^= val; 1915 - *dst++ ^= val; 1916 - n -= 4; 1917 - } 1918 - while (n--) 1919 - *dst++ ^= val; 1920 - 1921 - // Trailing bits 1922 - if (last) 1923 - *dst = xor(val, *dst, last); 1924 - } 1925 - } 1926 - 1927 - static inline void fill_one_line(int bpp, unsigned long next_plane, 1928 - unsigned long *dst, int dst_idx, u32 n, 1929 - u32 color) 1930 - { 1931 - while (1) { 1932 - dst += dst_idx >> SHIFT_PER_LONG; 1933 - dst_idx &= (BITS_PER_LONG-1); 1934 - bitfill32(dst, dst_idx, color & 1 ? ~0 : 0, n); 1935 - if (!--bpp) 1936 - break; 1937 - color >>= 1; 1938 - dst_idx += next_plane*8; 1939 - } 1940 - } 1941 - 1942 - static inline void xor_one_line(int bpp, unsigned long next_plane, 1943 - unsigned long *dst, int dst_idx, u32 n, 1944 - u32 color) 1945 - { 1946 - while (color) { 1947 - dst += dst_idx >> SHIFT_PER_LONG; 1948 - dst_idx &= (BITS_PER_LONG-1); 1949 - bitxor32(dst, dst_idx, color & 1 ? ~0 : 0, n); 1950 - if (!--bpp) 1951 - break; 1952 - color >>= 1; 1953 - dst_idx += next_plane*8; 1954 - } 1955 - } 1956 - 1957 - 1958 - static void amifb_fillrect(struct fb_info *info, 1959 - const struct fb_fillrect *rect) 1960 - { 1961 - struct amifb_par *par = (struct amifb_par *)info->par; 1962 - int dst_idx, x2, y2; 1963 - unsigned long *dst; 1964 - u32 width, height; 1965 - 1966 - if (!rect->width || !rect->height) 1967 - return; 1968 - 1969 - /* 1970 - * We could use hardware clipping but on many cards you get around 1971 - * hardware clipping by writing to framebuffer directly. 1972 - * */ 1973 - x2 = rect->dx + rect->width; 1974 - y2 = rect->dy + rect->height; 1975 - x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual; 1976 - y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual; 1977 - width = x2 - rect->dx; 1978 - height = y2 - rect->dy; 1979 - 1980 - dst = (unsigned long *) 1981 - ((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1)); 1982 - dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8; 1983 - dst_idx += rect->dy*par->next_line*8+rect->dx; 1984 - while (height--) { 1985 - switch (rect->rop) { 1986 - case ROP_COPY: 1987 - fill_one_line(info->var.bits_per_pixel, 1988 - par->next_plane, dst, dst_idx, width, 1989 - rect->color); 1990 - break; 1991 - 1992 - case ROP_XOR: 1993 - xor_one_line(info->var.bits_per_pixel, par->next_plane, 1994 - dst, dst_idx, width, rect->color); 1995 - break; 1996 - } 1997 - dst_idx += par->next_line*8; 1998 - } 1999 - } 2000 - 2001 - static inline void copy_one_line(int bpp, unsigned long next_plane, 2002 - unsigned long *dst, int dst_idx, 2003 - unsigned long *src, int src_idx, u32 n) 2004 - { 2005 - while (1) { 2006 - dst += dst_idx >> SHIFT_PER_LONG; 2007 - dst_idx &= (BITS_PER_LONG-1); 2008 - src += src_idx >> SHIFT_PER_LONG; 2009 - src_idx &= (BITS_PER_LONG-1); 2010 - bitcpy(dst, dst_idx, src, src_idx, n); 2011 - if (!--bpp) 2012 - break; 2013 - dst_idx += next_plane*8; 2014 - src_idx += next_plane*8; 2015 - } 2016 - } 2017 - 2018 - static inline void copy_one_line_rev(int bpp, unsigned long next_plane, 2019 - unsigned long *dst, int dst_idx, 2020 - unsigned long *src, int src_idx, u32 n) 2021 - { 2022 - while (1) { 2023 - dst += dst_idx >> SHIFT_PER_LONG; 2024 - dst_idx &= (BITS_PER_LONG-1); 2025 - src += src_idx >> SHIFT_PER_LONG; 2026 - src_idx &= (BITS_PER_LONG-1); 2027 - bitcpy_rev(dst, dst_idx, src, src_idx, n); 2028 - if (!--bpp) 2029 - break; 2030 - dst_idx += next_plane*8; 2031 - src_idx += next_plane*8; 2032 - } 2033 - } 2034 - 2035 - 2036 - static void amifb_copyarea(struct fb_info *info, 2037 - const struct fb_copyarea *area) 2038 - { 2039 - struct amifb_par *par = (struct amifb_par *)info->par; 2040 - int x2, y2; 2041 - u32 dx, dy, sx, sy, width, height; 2042 - unsigned long *dst, *src; 2043 - int dst_idx, src_idx; 2044 - int rev_copy = 0; 2045 - 2046 - /* clip the destination */ 2047 - x2 = area->dx + area->width; 2048 - y2 = area->dy + area->height; 2049 - dx = area->dx > 0 ? area->dx : 0; 2050 - dy = area->dy > 0 ? area->dy : 0; 2051 - x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual; 2052 - y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual; 2053 - width = x2 - dx; 2054 - height = y2 - dy; 2055 - 2056 - if (area->sx + dx < area->dx || area->sy + dy < area->dy) 2057 - return; 2058 - 2059 - /* update sx,sy */ 2060 - sx = area->sx + (dx - area->dx); 2061 - sy = area->sy + (dy - area->dy); 2062 - 2063 - /* the source must be completely inside the virtual screen */ 2064 - if (sx + width > info->var.xres_virtual || 2065 - sy + height > info->var.yres_virtual) 2066 - return; 2067 - 2068 - if (dy > sy || (dy == sy && dx > sx)) { 2069 - dy += height; 2070 - sy += height; 2071 - rev_copy = 1; 2072 - } 2073 - dst = (unsigned long *) 2074 - ((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1)); 2075 - src = dst; 2076 - dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8; 2077 - src_idx = dst_idx; 2078 - dst_idx += dy*par->next_line*8+dx; 2079 - src_idx += sy*par->next_line*8+sx; 2080 - if (rev_copy) { 2081 - while (height--) { 2082 - dst_idx -= par->next_line*8; 2083 - src_idx -= par->next_line*8; 2084 - copy_one_line_rev(info->var.bits_per_pixel, 2085 - par->next_plane, dst, dst_idx, src, 2086 - src_idx, width); 2087 - } 2088 - } else { 2089 - while (height--) { 2090 - copy_one_line(info->var.bits_per_pixel, 2091 - par->next_plane, dst, dst_idx, src, 2092 - src_idx, width); 2093 - dst_idx += par->next_line*8; 2094 - src_idx += par->next_line*8; 2095 - } 2096 - } 2097 - } 2098 - 2099 - 2100 - static inline void expand_one_line(int bpp, unsigned long next_plane, 2101 - unsigned long *dst, int dst_idx, u32 n, 2102 - const u8 *data, u32 bgcolor, u32 fgcolor) 2103 - { 2104 - const unsigned long *src; 2105 - int src_idx; 2106 - 2107 - while (1) { 2108 - dst += dst_idx >> SHIFT_PER_LONG; 2109 - dst_idx &= (BITS_PER_LONG-1); 2110 - if ((bgcolor ^ fgcolor) & 1) { 2111 - src = (unsigned long *)((unsigned long)data & ~(BYTES_PER_LONG-1)); 2112 - src_idx = ((unsigned long)data & (BYTES_PER_LONG-1))*8; 2113 - if (fgcolor & 1) 2114 - bitcpy(dst, dst_idx, src, src_idx, n); 2115 - else 2116 - bitcpy_not(dst, dst_idx, src, src_idx, n); 2117 - /* set or clear */ 2118 - } else 2119 - bitfill32(dst, dst_idx, fgcolor & 1 ? ~0 : 0, n); 2120 - if (!--bpp) 2121 - break; 2122 - bgcolor >>= 1; 2123 - fgcolor >>= 1; 2124 - dst_idx += next_plane*8; 2125 - } 2126 - } 2127 - 2128 - 2129 - static void amifb_imageblit(struct fb_info *info, const struct fb_image *image) 2130 - { 2131 - struct amifb_par *par = (struct amifb_par *)info->par; 2132 - int x2, y2; 2133 - unsigned long *dst; 2134 - int dst_idx; 2135 - const char *src; 2136 - u32 dx, dy, width, height, pitch; 2137 - 2138 - /* 2139 - * We could use hardware clipping but on many cards you get around 2140 - * hardware clipping by writing to framebuffer directly like we are 2141 - * doing here. 2142 - */ 2143 - x2 = image->dx + image->width; 2144 - y2 = image->dy + image->height; 2145 - dx = image->dx; 2146 - dy = image->dy; 2147 - x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual; 2148 - y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual; 2149 - width = x2 - dx; 2150 - height = y2 - dy; 2151 - 2152 - if (image->depth == 1) { 2153 - dst = (unsigned long *) 2154 - ((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1)); 2155 - dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8; 2156 - dst_idx += dy*par->next_line*8+dx; 2157 - src = image->data; 2158 - pitch = (image->width+7)/8; 2159 - while (height--) { 2160 - expand_one_line(info->var.bits_per_pixel, 2161 - par->next_plane, dst, dst_idx, width, 2162 - src, image->bg_color, 2163 - image->fg_color); 2164 - dst_idx += par->next_line*8; 2165 - src += pitch; 2166 - } 2167 - } else { 2168 - c2p_planar(info->screen_base, image->data, dx, dy, width, 2169 - height, par->next_line, par->next_plane, 2170 - image->width, info->var.bits_per_pixel); 2171 - } 2172 - } 2173 - 2174 - 2175 - /* 2176 - * Amiga Frame Buffer Specific ioctls 2177 - */ 2178 - 2179 - static int amifb_ioctl(struct fb_info *info, 2180 - unsigned int cmd, unsigned long arg) 2181 - { 2182 - union { 2183 - struct fb_fix_cursorinfo fix; 2184 - struct fb_var_cursorinfo var; 2185 - struct fb_cursorstate state; 2186 - } crsr; 2187 - void __user *argp = (void __user *)arg; 2188 - int i; 2189 - 2190 - switch (cmd) { 2191 - case FBIOGET_FCURSORINFO: 2192 - i = ami_get_fix_cursorinfo(&crsr.fix); 2193 - if (i) 2194 - return i; 2195 - return copy_to_user(argp, &crsr.fix, 2196 - sizeof(crsr.fix)) ? -EFAULT : 0; 2197 - 2198 - case FBIOGET_VCURSORINFO: 2199 - i = ami_get_var_cursorinfo(&crsr.var, 2200 - ((struct fb_var_cursorinfo __user *)arg)->data); 2201 - if (i) 2202 - return i; 2203 - return copy_to_user(argp, &crsr.var, 2204 - sizeof(crsr.var)) ? -EFAULT : 0; 2205 - 2206 - case FBIOPUT_VCURSORINFO: 2207 - if (copy_from_user(&crsr.var, argp, sizeof(crsr.var))) 2208 - return -EFAULT; 2209 - return ami_set_var_cursorinfo(&crsr.var, 2210 - ((struct fb_var_cursorinfo __user *)arg)->data); 2211 - 2212 - case FBIOGET_CURSORSTATE: 2213 - i = ami_get_cursorstate(&crsr.state); 2214 - if (i) 2215 - return i; 2216 - return copy_to_user(argp, &crsr.state, 2217 - sizeof(crsr.state)) ? -EFAULT : 0; 2218 - 2219 - case FBIOPUT_CURSORSTATE: 2220 - if (copy_from_user(&crsr.state, argp, 2221 - sizeof(crsr.state))) 2222 - return -EFAULT; 2223 - return ami_set_cursorstate(&crsr.state); 2224 - } 2225 - return -EINVAL; 2226 - } 2227 - 2228 - 2229 - /* 2230 - * Allocate, Clear and Align a Block of Chip Memory 2231 - */ 2232 - 2233 - static void *aligned_chipptr; 2234 - 2235 - static inline u_long __init chipalloc(u_long size) 2236 - { 2237 - aligned_chipptr = amiga_chip_alloc(size, "amifb [RAM]"); 2238 - if (!aligned_chipptr) { 2239 - pr_err("amifb: No Chip RAM for frame buffer"); 2240 - return 0; 2241 - } 2242 - memset(aligned_chipptr, 0, size); 2243 - return (u_long)aligned_chipptr; 2244 - } 2245 - 2246 - static inline void chipfree(void) 2247 - { 2248 - if (aligned_chipptr) 2249 - amiga_chip_free(aligned_chipptr); 2250 - } 2251 - 2252 - 2253 - /* 2254 - * Initialisation 2255 - */ 2256 - 2257 - static int __init amifb_probe(struct platform_device *pdev) 2258 - { 2259 - int tag, i, err = 0; 2260 - u_long chipptr; 2261 - u_int defmode; 2262 - 2263 - #ifndef MODULE 2264 - char *option = NULL; 2265 - 2266 - if (fb_get_options("amifb", &option)) { 2267 - amifb_video_off(); 2268 - return -ENODEV; 2269 - } 2270 - amifb_setup(option); 2271 - #endif 2272 - custom.dmacon = DMAF_ALL | DMAF_MASTER; 2273 - 2274 - switch (amiga_chipset) { 2275 - #ifdef CONFIG_FB_AMIGA_OCS 2276 - case CS_OCS: 2277 - strcat(fb_info.fix.id, "OCS"); 2278 - default_chipset: 2279 - chipset = TAG_OCS; 2280 - maxdepth[TAG_SHRES] = 0; /* OCS means no SHRES */ 2281 - maxdepth[TAG_HIRES] = 4; 2282 - maxdepth[TAG_LORES] = 6; 2283 - maxfmode = TAG_FMODE_1; 2284 - defmode = amiga_vblank == 50 ? DEFMODE_PAL 2285 - : DEFMODE_NTSC; 2286 - fb_info.fix.smem_len = VIDEOMEMSIZE_OCS; 2287 - break; 2288 - #endif /* CONFIG_FB_AMIGA_OCS */ 2289 - 2290 - #ifdef CONFIG_FB_AMIGA_ECS 2291 - case CS_ECS: 2292 - strcat(fb_info.fix.id, "ECS"); 2293 - chipset = TAG_ECS; 2294 - maxdepth[TAG_SHRES] = 2; 2295 - maxdepth[TAG_HIRES] = 4; 2296 - maxdepth[TAG_LORES] = 6; 2297 - maxfmode = TAG_FMODE_1; 2298 - if (AMIGAHW_PRESENT(AMBER_FF)) 2299 - defmode = amiga_vblank == 50 ? DEFMODE_AMBER_PAL 2300 - : DEFMODE_AMBER_NTSC; 2301 - else 2302 - defmode = amiga_vblank == 50 ? DEFMODE_PAL 2303 - : DEFMODE_NTSC; 2304 - if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT > 2305 - VIDEOMEMSIZE_ECS_2M) 2306 - fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_2M; 2307 - else 2308 - fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_1M; 2309 - break; 2310 - #endif /* CONFIG_FB_AMIGA_ECS */ 2311 - 2312 - #ifdef CONFIG_FB_AMIGA_AGA 2313 - case CS_AGA: 2314 - strcat(fb_info.fix.id, "AGA"); 2315 - chipset = TAG_AGA; 2316 - maxdepth[TAG_SHRES] = 8; 2317 - maxdepth[TAG_HIRES] = 8; 2318 - maxdepth[TAG_LORES] = 8; 2319 - maxfmode = TAG_FMODE_4; 2320 - defmode = DEFMODE_AGA; 2321 - if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT > 2322 - VIDEOMEMSIZE_AGA_2M) 2323 - fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_2M; 2324 - else 2325 - fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_1M; 2326 - break; 2327 - #endif /* CONFIG_FB_AMIGA_AGA */ 2328 - 2329 - default: 2330 - #ifdef CONFIG_FB_AMIGA_OCS 2331 - printk("Unknown graphics chipset, defaulting to OCS\n"); 2332 - strcat(fb_info.fix.id, "Unknown"); 2333 - goto default_chipset; 2334 - #else /* CONFIG_FB_AMIGA_OCS */ 2335 - err = -ENODEV; 2336 - goto amifb_error; 2337 - #endif /* CONFIG_FB_AMIGA_OCS */ 2338 - break; 2339 - } 2340 - 2341 - /* 2342 - * Calculate the Pixel Clock Values for this Machine 2343 - */ 2344 - 2345 - { 2346 - u_long tmp = DIVUL(200000000000ULL, amiga_eclock); 2347 - 2348 - pixclock[TAG_SHRES] = (tmp + 4) / 8; /* SHRES: 35 ns / 28 MHz */ 2349 - pixclock[TAG_HIRES] = (tmp + 2) / 4; /* HIRES: 70 ns / 14 MHz */ 2350 - pixclock[TAG_LORES] = (tmp + 1) / 2; /* LORES: 140 ns / 7 MHz */ 2351 - } 2352 - 2353 - /* 2354 - * Replace the Tag Values with the Real Pixel Clock Values 2355 - */ 2356 - 2357 - for (i = 0; i < NUM_TOTAL_MODES; i++) { 2358 - struct fb_videomode *mode = &ami_modedb[i]; 2359 - tag = mode->pixclock; 2360 - if (tag == TAG_SHRES || tag == TAG_HIRES || tag == TAG_LORES) { 2361 - mode->pixclock = pixclock[tag]; 2362 - } 2363 - } 2364 - 2365 - /* 2366 - * These monitor specs are for a typical Amiga monitor (e.g. A1960) 2367 - */ 2368 - if (fb_info.monspecs.hfmin == 0) { 2369 - fb_info.monspecs.hfmin = 15000; 2370 - fb_info.monspecs.hfmax = 38000; 2371 - fb_info.monspecs.vfmin = 49; 2372 - fb_info.monspecs.vfmax = 90; 2373 - } 2374 - 2375 - fb_info.fbops = &amifb_ops; 2376 - fb_info.par = &currentpar; 2377 - fb_info.flags = FBINFO_DEFAULT; 2378 - fb_info.device = &pdev->dev; 2379 - 2380 - if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb, 2381 - NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) { 2382 - err = -EINVAL; 2383 - goto amifb_error; 2384 - } 2385 - 2386 - fb_videomode_to_modelist(ami_modedb, NUM_TOTAL_MODES, 2387 - &fb_info.modelist); 2388 - 2389 - round_down_bpp = 0; 2390 - chipptr = chipalloc(fb_info.fix.smem_len+ 2391 - SPRITEMEMSIZE+ 2392 - DUMMYSPRITEMEMSIZE+ 2393 - COPINITSIZE+ 2394 - 4*COPLISTSIZE); 2395 - if (!chipptr) { 2396 - err = -ENOMEM; 2397 - goto amifb_error; 2398 - } 2399 - 2400 - assignchunk(videomemory, u_long, chipptr, fb_info.fix.smem_len); 2401 - assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE); 2402 - assignchunk(dummysprite, u_short *, chipptr, DUMMYSPRITEMEMSIZE); 2403 - assignchunk(copdisplay.init, copins *, chipptr, COPINITSIZE); 2404 - assignchunk(copdisplay.list[0][0], copins *, chipptr, COPLISTSIZE); 2405 - assignchunk(copdisplay.list[0][1], copins *, chipptr, COPLISTSIZE); 2406 - assignchunk(copdisplay.list[1][0], copins *, chipptr, COPLISTSIZE); 2407 - assignchunk(copdisplay.list[1][1], copins *, chipptr, COPLISTSIZE); 2408 - 2409 - /* 2410 - * access the videomem with writethrough cache 2411 - */ 2412 - fb_info.fix.smem_start = (u_long)ZTWO_PADDR(videomemory); 2413 - videomemory = (u_long)ioremap_writethrough(fb_info.fix.smem_start, 2414 - fb_info.fix.smem_len); 2415 - if (!videomemory) { 2416 - printk("amifb: WARNING! unable to map videomem cached writethrough\n"); 2417 - fb_info.screen_base = (char *)ZTWO_VADDR(fb_info.fix.smem_start); 2418 - } else 2419 - fb_info.screen_base = (char *)videomemory; 2420 - 2421 - memset(dummysprite, 0, DUMMYSPRITEMEMSIZE); 2422 - 2423 - /* 2424 - * Enable Display DMA 2425 - */ 2426 - 2427 - custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER | 2428 - DMAF_BLITTER | DMAF_SPRITE; 2429 - 2430 - /* 2431 - * Make sure the Copper has something to do 2432 - */ 2433 - 2434 - ami_init_copper(); 2435 - 2436 - if (request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, 0, 2437 - "fb vertb handler", &currentpar)) { 2438 - err = -EBUSY; 2439 - goto amifb_error; 2440 - } 2441 - 2442 - err = fb_alloc_cmap(&fb_info.cmap, 1<<fb_info.var.bits_per_pixel, 0); 2443 - if (err) 2444 - goto amifb_error; 2445 - 2446 - if (register_framebuffer(&fb_info) < 0) { 2447 - err = -EINVAL; 2448 - goto amifb_error; 2449 - } 2450 - 2451 - printk("fb%d: %s frame buffer device, using %dK of video memory\n", 2452 - fb_info.node, fb_info.fix.id, fb_info.fix.smem_len>>10); 2453 - 2454 - return 0; 2455 - 2456 - amifb_error: 2457 - amifb_deinit(pdev); 2458 - return err; 2459 - } 2460 - 2461 - static void amifb_deinit(struct platform_device *pdev) 2462 - { 2463 - if (fb_info.cmap.len) 2464 - fb_dealloc_cmap(&fb_info.cmap); 2465 - fb_dealloc_cmap(&fb_info.cmap); 2466 - chipfree(); 2467 - if (videomemory) 2468 - iounmap((void*)videomemory); 2469 - custom.dmacon = DMAF_ALL | DMAF_MASTER; 2470 - } 2471 - 2472 - 2473 - /* 2474 - * Blank the display. 2475 - */ 2476 - 2477 - static int amifb_blank(int blank, struct fb_info *info) 2478 - { 2479 - do_blank = blank ? blank : -1; 2480 - 2481 - return 0; 2482 - } 2483 - 2484 - /* 2485 - * Flash the cursor (called by VBlank interrupt) 2486 - */ 2487 - 2488 - static int flash_cursor(void) 2489 - { 2490 - static int cursorcount = 1; 2491 - 2492 - if (cursormode == FB_CURSOR_FLASH) { 2493 - if (!--cursorcount) { 2494 - cursorstate = -cursorstate; 2495 - cursorcount = cursorrate; 2496 - if (!is_blanked) 2497 - return 1; 2498 - } 2499 - } 2500 - return 0; 2501 - } 2502 - 2503 - /* 2504 - * VBlank Display Interrupt 2505 - */ 2506 - 2507 - static irqreturn_t amifb_interrupt(int irq, void *dev_id) 2508 - { 2509 - if (do_vmode_pan || do_vmode_full) 2510 - ami_update_display(); 2511 - 2512 - if (do_vmode_full) 2513 - ami_init_display(); 2514 - 2515 - if (do_vmode_pan) { 2516 - flash_cursor(); 2517 - ami_rebuild_copper(); 2518 - do_cursor = do_vmode_pan = 0; 2519 - } else if (do_cursor) { 2520 - flash_cursor(); 2521 - ami_set_sprite(); 2522 - do_cursor = 0; 2523 - } else { 2524 - if (flash_cursor()) 2525 - ami_set_sprite(); 2526 - } 2527 - 2528 - if (do_blank) { 2529 - ami_do_blank(); 2530 - do_blank = 0; 2531 - } 2532 - 2533 - if (do_vmode_full) { 2534 - ami_reinit_copper(); 2535 - do_vmode_full = 0; 2536 - } 2537 - return IRQ_HANDLED; 2538 - } 2539 - 2540 1111 /* --------------------------- Hardware routines --------------------------- */ 2541 1112 2542 1113 /* ··· 1121 2538 * it up, if it's too big, return -EINVAL. 1122 2539 */ 1123 2540 1124 - static int ami_decode_var(struct fb_var_screeninfo *var, 1125 - struct amifb_par *par) 2541 + static int ami_decode_var(struct fb_var_screeninfo *var, struct amifb_par *par, 2542 + const struct fb_info *info) 1126 2543 { 1127 2544 u_short clk_shift, line_shift; 1128 2545 u_long maxfetchstop, fstrt, fsize, fconst, xres_n, yres_n; ··· 1189 2606 1190 2607 par->vmode = var->vmode | FB_VMODE_SMOOTH_XPAN; 1191 2608 switch (par->vmode & FB_VMODE_MASK) { 1192 - case FB_VMODE_INTERLACED: 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"); 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"); 1207 2618 return -EINVAL; 1208 - break; 2619 + } 2620 + line_shift = 2; 2621 + break; 2622 + default: 2623 + DPRINTK("unknown video mode\n"); 2624 + return -EINVAL; 2625 + break; 1209 2626 } 1210 2627 par->line_shift = line_shift; 1211 2628 ··· 1213 2630 * Vertical and Horizontal Timings 1214 2631 */ 1215 2632 1216 - xres_n = par->xres<<clk_shift; 1217 - yres_n = par->yres<<line_shift; 1218 - par->htotal = down8((var->left_margin+par->xres+var->right_margin+var->hsync_len)<<clk_shift); 1219 - par->vtotal = down2(((var->upper_margin+par->yres+var->lower_margin+var->vsync_len)<<line_shift)+1); 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 + 2636 + var->hsync_len) << clk_shift); 2637 + par->vtotal = 2638 + down2(((var->upper_margin + par->yres + var->lower_margin + 2639 + var->vsync_len) << line_shift) + 1); 1220 2640 1221 2641 if (IS_AGA) 1222 2642 par->bplcon3 = sprpixmode[clk_shift]; 1223 2643 else 1224 2644 par->bplcon3 = 0; 1225 2645 if (var->sync & FB_SYNC_BROADCAST) { 1226 - par->diwstop_h = par->htotal-((var->right_margin-var->hsync_len)<<clk_shift); 2646 + par->diwstop_h = par->htotal - 2647 + ((var->right_margin - var->hsync_len) << clk_shift); 1227 2648 if (IS_AGA) 1228 2649 par->diwstop_h += mod4(var->hsync_len); 1229 2650 else 1230 2651 par->diwstop_h = down4(par->diwstop_h); 1231 2652 1232 2653 par->diwstrt_h = par->diwstop_h - xres_n; 1233 - par->diwstop_v = par->vtotal-((var->lower_margin-var->vsync_len)<<line_shift); 2654 + par->diwstop_v = par->vtotal - 2655 + ((var->lower_margin - var->vsync_len) << line_shift); 1234 2656 par->diwstrt_v = par->diwstop_v - yres_n; 1235 - if (par->diwstop_h >= par->htotal+8) { 2657 + if (par->diwstop_h >= par->htotal + 8) { 1236 2658 DPRINTK("invalid diwstop_h\n"); 1237 2659 return -EINVAL; 1238 2660 } ··· 1258 2670 par->vsstrt = 0; 1259 2671 par->vsstop = 0; 1260 2672 } 1261 - if (par->vtotal > (PAL_VTOTAL+NTSC_VTOTAL)/2) { 2673 + if (par->vtotal > (PAL_VTOTAL + NTSC_VTOTAL) / 2) { 1262 2674 /* PAL video mode */ 1263 2675 if (par->htotal != PAL_HTOTAL) { 1264 2676 DPRINTK("htotal invalid for pal\n"); ··· 1278 2690 par->beamcon0 = BMC0_PAL; 1279 2691 par->bplcon3 |= BPC3_BRDRBLNK; 1280 2692 } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) || 1281 - AMIGAHW_PRESENT(AGNUS_HR_NTSC)) { 2693 + AMIGAHW_PRESENT(AGNUS_HR_NTSC)) { 1282 2694 par->beamcon0 = BMC0_PAL; 1283 2695 par->hsstop = 1; 1284 2696 } else if (amiga_vblank != 50) { ··· 1308 2720 par->beamcon0 = 0; 1309 2721 par->bplcon3 |= BPC3_BRDRBLNK; 1310 2722 } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) || 1311 - AMIGAHW_PRESENT(AGNUS_HR_NTSC)) { 2723 + AMIGAHW_PRESENT(AGNUS_HR_NTSC)) { 1312 2724 par->beamcon0 = 0; 1313 2725 par->hsstop = 1; 1314 2726 } else if (amiga_vblank != 60) { ··· 1325 2737 } 1326 2738 } else if (!IS_OCS) { 1327 2739 /* Programmable video mode */ 1328 - par->hsstrt = var->right_margin<<clk_shift; 1329 - par->hsstop = (var->right_margin+var->hsync_len)<<clk_shift; 2740 + par->hsstrt = var->right_margin << clk_shift; 2741 + par->hsstop = (var->right_margin + var->hsync_len) << clk_shift; 1330 2742 par->diwstop_h = par->htotal - mod8(par->hsstrt) + 8 - (1 << clk_shift); 1331 2743 if (!IS_AGA) 1332 2744 par->diwstop_h = down4(par->diwstop_h) - 16; ··· 1336 2748 if (par->hbstrt >= par->htotal + 8) 1337 2749 par->hbstrt -= par->htotal; 1338 2750 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; 2751 + par->vsstrt = var->lower_margin << line_shift; 2752 + par->vsstop = (var->lower_margin + var->vsync_len) << line_shift; 1341 2753 par->diwstop_v = par->vtotal; 1342 2754 if ((par->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) 1343 2755 par->diwstop_v -= 2; ··· 1354 2766 } 1355 2767 par->bplcon3 |= BPC3_EXTBLKEN; 1356 2768 par->beamcon0 = BMC0_HARDDIS | BMC0_VARVBEN | BMC0_LOLDIS | 1357 - BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARBEAMEN | 1358 - BMC0_PAL | BMC0_VARCSYEN; 2769 + BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARBEAMEN | 2770 + BMC0_PAL | BMC0_VARCSYEN; 1359 2771 if (var->sync & FB_SYNC_HOR_HIGH_ACT) 1360 2772 par->beamcon0 |= BMC0_HSYTRUE; 1361 2773 if (var->sync & FB_SYNC_VERT_HIGH_ACT) ··· 1373 2785 * Checking the DMA timing 1374 2786 */ 1375 2787 1376 - fconst = 16<<maxfmode<<clk_shift; 2788 + fconst = 16 << maxfmode << clk_shift; 1377 2789 1378 2790 /* 1379 2791 * smallest window start value without turn off other dma cycles ··· 1381 2793 */ 1382 2794 1383 2795 1384 - fsize = ((maxfmode+clk_shift <= 1) ? fconst : 64); 1385 - fstrt = downx(fconst, par->diwstrt_h-4) - fsize; 2796 + fsize = ((maxfmode + clk_shift <= 1) ? fconst : 64); 2797 + fstrt = downx(fconst, par->diwstrt_h - 4) - fsize; 1386 2798 if (fstrt < min_fstrt) { 1387 2799 DPRINTK("fetch start too low\n"); 1388 2800 return -EINVAL; ··· 1392 2804 * smallest window start value where smooth scrolling is possible 1393 2805 */ 1394 2806 1395 - fstrt = downx(fconst, par->diwstrt_h-fconst+(1<<clk_shift)-4) - fsize; 2807 + fstrt = downx(fconst, par->diwstrt_h - fconst + (1 << clk_shift) - 4) - 2808 + fsize; 1396 2809 if (fstrt < min_fstrt) 1397 2810 par->vmode &= ~FB_VMODE_SMOOTH_XPAN; 1398 2811 1399 2812 maxfetchstop = down16(par->htotal - 80); 1400 2813 1401 - fstrt = downx(fconst, par->diwstrt_h-4) - 64 - fconst; 1402 - fsize = upx(fconst, xres_n + modx(fconst, downx(1<<clk_shift, par->diwstrt_h-4))); 2814 + fstrt = downx(fconst, par->diwstrt_h - 4) - 64 - fconst; 2815 + fsize = upx(fconst, xres_n + 2816 + modx(fconst, downx(1 << clk_shift, par->diwstrt_h - 4))); 1403 2817 if (fstrt + fsize > maxfetchstop) 1404 2818 par->vmode &= ~FB_VMODE_SMOOTH_XPAN; 1405 2819 ··· 1430 2840 * Check if there is enough time to update the bitplane pointers for ywrap 1431 2841 */ 1432 2842 1433 - if (par->htotal-fsize-64 < par->bpp*64) 2843 + if (par->htotal - fsize - 64 < par->bpp * 64) 1434 2844 par->vmode &= ~FB_VMODE_YWRAP; 1435 2845 1436 2846 /* ··· 1438 2848 */ 1439 2849 1440 2850 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 > fb_info.fix.smem_len) { 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 > info->fix.smem_len) { 1444 2854 DPRINTK("too few video mem\n"); 1445 2855 return -EINVAL; 1446 2856 } 1447 2857 } 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 > fb_info.fix.smem_len) { 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 > info->fix.smem_len) { 1451 2861 DPRINTK("too few video mem\n"); 1452 2862 return -EINVAL; 1453 2863 } ··· 1463 2873 if (par->bpp == 8) 1464 2874 par->bplcon0 |= BPC0_BPU3; 1465 2875 else 1466 - par->bplcon0 |= par->bpp<<12; 2876 + par->bplcon0 |= par->bpp << 12; 1467 2877 if (var->nonstd == FB_NONSTD_HAM) 1468 2878 par->bplcon0 |= BPC0_HAM; 1469 2879 if (var->sync & FB_SYNC_EXT) ··· 1473 2883 par->fmode = bplfetchmode[maxfmode]; 1474 2884 1475 2885 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; 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; 1483 2893 } 1484 2894 1485 2895 if (!((par->vmode ^ var->vmode) & FB_VMODE_YWRAP)) { 1486 2896 par->xoffset = var->xoffset; 1487 2897 par->yoffset = var->yoffset; 1488 2898 if (par->vmode & FB_VMODE_YWRAP) { 1489 - if (par->xoffset || par->yoffset < 0 || par->yoffset >= par->vyres) 2899 + if (par->xoffset || par->yoffset < 0 || 2900 + par->yoffset >= par->vyres) 1490 2901 par->xoffset = par->yoffset = 0; 1491 2902 } else { 1492 - if (par->xoffset < 0 || par->xoffset > upx(16<<maxfmode, par->vxres-par->xres) || 1493 - par->yoffset < 0 || par->yoffset > par->vyres-par->yres) 2903 + if (par->xoffset < 0 || 2904 + par->xoffset > upx(16 << maxfmode, par->vxres - par->xres) || 2905 + par->yoffset < 0 || par->yoffset > par->vyres - par->yres) 1494 2906 par->xoffset = par->yoffset = 0; 1495 2907 } 1496 2908 } else ··· 1510 2918 * other values read out of the hardware. 1511 2919 */ 1512 2920 1513 - static int ami_encode_var(struct fb_var_screeninfo *var, 1514 - struct amifb_par *par) 2921 + static void ami_encode_var(struct fb_var_screeninfo *var, 2922 + struct amifb_par *par) 1515 2923 { 1516 2924 u_short clk_shift, line_shift; 1517 2925 ··· 1534 2942 var->red.msb_right = 0; 1535 2943 var->red.length = par->bpp; 1536 2944 if (par->bplcon0 & BPC0_HAM) 1537 - var->red.length -= 2; 2945 + var->red.length -= 2; 1538 2946 var->blue = var->green = var->red; 1539 2947 var->transp.offset = 0; 1540 2948 var->transp.length = 0; ··· 1559 2967 var->vmode = FB_VMODE_NONINTERLACED; 1560 2968 1561 2969 if (!IS_OCS && par->beamcon0 & BMC0_VARBEAMEN) { 1562 - var->hsync_len = (par->hsstop-par->hsstrt)>>clk_shift; 2970 + var->hsync_len = (par->hsstop - par->hsstrt)>>clk_shift; 1563 2971 var->right_margin = par->hsstrt>>clk_shift; 1564 2972 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; 2973 + var->vsync_len = (par->vsstop - par->vsstrt)>>line_shift; 1566 2974 var->lower_margin = par->vsstrt>>line_shift; 1567 2975 var->upper_margin = (par->vtotal>>line_shift) - var->yres - var->lower_margin - var->vsync_len; 1568 2976 var->sync = 0; ··· 1580 2988 var->vsync_len = 4>>line_shift; 1581 2989 var->lower_margin = ((par->vtotal - par->diwstop_v)>>line_shift) + var->vsync_len; 1582 2990 var->upper_margin = (((par->vtotal - 2)>>line_shift) + 1) - var->yres - 1583 - var->lower_margin - var->vsync_len; 2991 + var->lower_margin - var->vsync_len; 1584 2992 } 1585 2993 1586 2994 if (par->bplcon0 & BPC0_ERSY) 1587 2995 var->sync |= FB_SYNC_EXT; 1588 2996 if (par->vmode & FB_VMODE_YWRAP) 1589 2997 var->vmode |= FB_VMODE_YWRAP; 1590 - 1591 - return 0; 1592 2998 } 1593 2999 1594 - 1595 - /* 1596 - * Pan or Wrap the Display 1597 - * 1598 - * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag 1599 - * in `var'. 1600 - */ 1601 - 1602 - static void ami_pan_var(struct fb_var_screeninfo *var) 1603 - { 1604 - struct amifb_par *par = &currentpar; 1605 - 1606 - par->xoffset = var->xoffset; 1607 - par->yoffset = var->yoffset; 1608 - if (var->vmode & FB_VMODE_YWRAP) 1609 - par->vmode |= FB_VMODE_YWRAP; 1610 - else 1611 - par->vmode &= ~FB_VMODE_YWRAP; 1612 - 1613 - do_vmode_pan = 0; 1614 - ami_update_par(); 1615 - do_vmode_pan = 1; 1616 - } 1617 3000 1618 3001 /* 1619 3002 * Update hardware 1620 3003 */ 1621 3004 1622 - static int ami_update_par(void) 3005 + static void ami_update_par(struct fb_info *info) 1623 3006 { 1624 - struct amifb_par *par = &currentpar; 3007 + struct amifb_par *par = info->par; 1625 3008 short clk_shift, vshift, fstrt, fsize, fstop, fconst, shift, move, mod; 1626 3009 1627 3010 clk_shift = par->clk_shift; 1628 3011 1629 3012 if (!(par->vmode & FB_VMODE_SMOOTH_XPAN)) 1630 - par->xoffset = upx(16<<maxfmode, par->xoffset); 3013 + par->xoffset = upx(16 << maxfmode, par->xoffset); 1631 3014 1632 - fconst = 16<<maxfmode<<clk_shift; 1633 - vshift = modx(16<<maxfmode, par->xoffset); 1634 - fstrt = par->diwstrt_h - (vshift<<clk_shift) - 4; 1635 - fsize = (par->xres+vshift)<<clk_shift; 3015 + fconst = 16 << maxfmode << clk_shift; 3016 + vshift = modx(16 << maxfmode, par->xoffset); 3017 + fstrt = par->diwstrt_h - (vshift << clk_shift) - 4; 3018 + fsize = (par->xres + vshift) << clk_shift; 1636 3019 shift = modx(fconst, fstrt); 1637 - move = downx(2<<maxfmode, div8(par->xoffset)); 3020 + move = downx(2 << maxfmode, div8(par->xoffset)); 1638 3021 if (maxfmode + clk_shift > 1) { 1639 3022 fstrt = downx(fconst, fstrt) - 64; 1640 3023 fsize = upx(fconst, fsize); ··· 1623 3056 fstop += min_fstrt - fstrt; 1624 3057 fstrt = min_fstrt; 1625 3058 } 1626 - move = move - div8((mod-fstrt)>>clk_shift); 3059 + move = move - div8((mod - fstrt)>>clk_shift); 1627 3060 } 1628 3061 mod = par->next_line - div8(fsize>>clk_shift); 1629 3062 par->ddfstrt = fstrt; ··· 1638 3071 par->bpl1mod = par->bpl2mod; 1639 3072 1640 3073 if (par->yoffset) { 1641 - par->bplpt0 = fb_info.fix.smem_start + par->next_line*par->yoffset + move; 3074 + par->bplpt0 = info->fix.smem_start + 3075 + par->next_line * par->yoffset + move; 1642 3076 if (par->vmode & FB_VMODE_YWRAP) { 1643 - if (par->yoffset > par->vyres-par->yres) { 1644 - par->bplpt0wrap = fb_info.fix.smem_start + move; 1645 - if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v+par->vyres-par->yoffset)) 3077 + if (par->yoffset > par->vyres - par->yres) { 3078 + par->bplpt0wrap = info->fix.smem_start + move; 3079 + if (par->bplcon0 & BPC0_LACE && 3080 + mod2(par->diwstrt_v + par->vyres - 3081 + par->yoffset)) 1646 3082 par->bplpt0wrap += par->next_line; 1647 3083 } 1648 3084 } 1649 3085 } else 1650 - par->bplpt0 = fb_info.fix.smem_start + move; 3086 + par->bplpt0 = info->fix.smem_start + move; 1651 3087 1652 3088 if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v)) 1653 3089 par->bplpt0 += par->next_line; 1654 - 1655 - return 0; 1656 3090 } 1657 3091 1658 3092 1659 3093 /* 1660 - * Set a single color register. The values supplied are already 1661 - * rounded down to the hardware's capabilities (according to the 1662 - * entries in the var structure). Return != 0 for invalid regno. 1663 - */ 1664 - 1665 - static int amifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, 1666 - u_int transp, struct fb_info *info) 1667 - { 1668 - if (IS_AGA) { 1669 - if (regno > 255) 1670 - return 1; 1671 - } else if (currentpar.bplcon0 & BPC0_SHRES) { 1672 - if (regno > 3) 1673 - return 1; 1674 - } else { 1675 - if (regno > 31) 1676 - return 1; 1677 - } 1678 - red >>= 8; 1679 - green >>= 8; 1680 - blue >>= 8; 1681 - if (!regno) { 1682 - red0 = red; 1683 - green0 = green; 1684 - blue0 = blue; 1685 - } 1686 - 1687 - /* 1688 - * Update the corresponding Hardware Color Register, unless it's Color 1689 - * Register 0 and the screen is blanked. 3094 + * Pan or Wrap the Display 1690 3095 * 1691 - * VBlank is switched off to protect bplcon3 or ecs_palette[] from 1692 - * being changed by ami_do_blank() during the VBlank. 3096 + * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag 3097 + * in `var'. 1693 3098 */ 1694 3099 1695 - if (regno || !is_blanked) { 1696 - #if defined(CONFIG_FB_AMIGA_AGA) 1697 - if (IS_AGA) { 1698 - u_short bplcon3 = currentpar.bplcon3; 1699 - VBlankOff(); 1700 - custom.bplcon3 = bplcon3 | (regno<<8 & 0xe000); 1701 - custom.color[regno&31] = rgb2hw8_high(red, green, blue); 1702 - custom.bplcon3 = bplcon3 | (regno<<8 & 0xe000) | BPC3_LOCT; 1703 - custom.color[regno&31] = rgb2hw8_low(red, green, blue); 1704 - custom.bplcon3 = bplcon3; 1705 - VBlankOn(); 1706 - } else 1707 - #endif 1708 - #if defined(CONFIG_FB_AMIGA_ECS) 1709 - if (currentpar.bplcon0 & BPC0_SHRES) { 1710 - u_short color, mask; 1711 - int i; 3100 + static void ami_pan_var(struct fb_var_screeninfo *var, struct fb_info *info) 3101 + { 3102 + struct amifb_par *par = info->par; 1712 3103 1713 - mask = 0x3333; 1714 - color = rgb2hw2(red, green, blue); 1715 - VBlankOff(); 1716 - for (i = regno+12; i >= (int)regno; i -= 4) 1717 - custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color; 1718 - mask <<=2; color >>= 2; 1719 - regno = down16(regno)+mul4(mod4(regno)); 1720 - for (i = regno+3; i >= (int)regno; i--) 1721 - custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color; 1722 - VBlankOn(); 1723 - } else 1724 - #endif 1725 - custom.color[regno] = rgb2hw4(red, green, blue); 1726 - } 1727 - return 0; 3104 + par->xoffset = var->xoffset; 3105 + par->yoffset = var->yoffset; 3106 + if (var->vmode & FB_VMODE_YWRAP) 3107 + par->vmode |= FB_VMODE_YWRAP; 3108 + else 3109 + par->vmode &= ~FB_VMODE_YWRAP; 3110 + 3111 + do_vmode_pan = 0; 3112 + ami_update_par(info); 3113 + do_vmode_pan = 1; 1728 3114 } 1729 3115 1730 - static void ami_update_display(void) 1731 - { 1732 - struct amifb_par *par = &currentpar; 1733 3116 3117 + static void ami_update_display(const struct amifb_par *par) 3118 + { 1734 3119 custom.bplcon1 = par->bplcon1; 1735 3120 custom.bpl1mod = par->bpl1mod; 1736 3121 custom.bpl2mod = par->bpl2mod; ··· 1694 3175 * Change the video mode (called by VBlank interrupt) 1695 3176 */ 1696 3177 1697 - static void ami_init_display(void) 3178 + static void ami_init_display(const struct amifb_par *par) 1698 3179 { 1699 - struct amifb_par *par = &currentpar; 1700 3180 int i; 1701 3181 1702 3182 custom.bplcon0 = par->bplcon0 & ~BPC0_LACE; ··· 1748 3230 * (Un)Blank the screen (called by VBlank interrupt) 1749 3231 */ 1750 3232 1751 - static void ami_do_blank(void) 3233 + static void ami_do_blank(const struct amifb_par *par) 1752 3234 { 1753 - struct amifb_par *par = &currentpar; 1754 3235 #if defined(CONFIG_FB_AMIGA_AGA) 1755 3236 u_short bplcon3 = par->bplcon3; 1756 3237 #endif ··· 1760 3243 red = green = blue = 0; 1761 3244 if (!IS_OCS && do_blank > 1) { 1762 3245 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; 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; 1781 3264 } 1782 3265 if (!(par->beamcon0 & BMC0_VARBEAMEN)) { 1783 3266 custom.htotal = htotal2hw(par->htotal); 1784 3267 custom.vtotal = vtotal2hw(par->vtotal); 1785 3268 custom.beamcon0 = BMC0_HARDDIS | BMC0_VARBEAMEN | 1786 - BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARCSYEN; 3269 + BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARCSYEN; 1787 3270 } 1788 3271 } 1789 3272 } else { ··· 1817 3300 color = rgb2hw2(red, green, blue); 1818 3301 for (i = 12; i >= 0; i -= 4) 1819 3302 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color; 1820 - mask <<=2; color >>= 2; 3303 + mask <<= 2; color >>= 2; 1821 3304 for (i = 3; i >= 0; i--) 1822 3305 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color; 1823 3306 } else ··· 1826 3309 is_blanked = do_blank > 0 ? do_blank : 0; 1827 3310 } 1828 3311 1829 - static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix) 3312 + static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix, 3313 + const struct amifb_par *par) 1830 3314 { 1831 - struct amifb_par *par = &currentpar; 1832 - 1833 3315 fix->crsr_width = fix->crsr_xsize = par->crsr.width; 1834 3316 fix->crsr_height = fix->crsr_ysize = par->crsr.height; 1835 3317 fix->crsr_color1 = 17; ··· 1836 3320 return 0; 1837 3321 } 1838 3322 1839 - static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data) 3323 + static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, 3324 + u_char __user *data, 3325 + const struct amifb_par *par) 1840 3326 { 1841 - struct amifb_par *par = &currentpar; 1842 3327 register u_short *lspr, *sspr; 1843 3328 #ifdef __mc68000__ 1844 3329 register u_long datawords asm ("d2"); ··· 1851 3334 short height, width, bits, words; 1852 3335 int size, alloc; 1853 3336 1854 - size = par->crsr.height*par->crsr.width; 1855 - alloc = var->height*var->width; 3337 + size = par->crsr.height * par->crsr.width; 3338 + alloc = var->height * var->width; 1856 3339 var->height = par->crsr.height; 1857 3340 var->width = par->crsr.width; 1858 3341 var->xspot = par->crsr.spot_x; 1859 3342 var->yspot = par->crsr.spot_y; 1860 - if (size > var->height*var->width) 3343 + if (size > var->height * var->width) 1861 3344 return -ENAMETOOLONG; 1862 3345 if (!access_ok(VERIFY_WRITE, data, size)) 1863 3346 return -EFAULT; 1864 - delta = 1<<par->crsr.fmode; 1865 - lspr = lofsprite + (delta<<1); 3347 + delta = 1 << par->crsr.fmode; 3348 + lspr = lofsprite + (delta << 1); 1866 3349 if (par->bplcon0 & BPC0_LACE) 1867 - sspr = shfsprite + (delta<<1); 3350 + sspr = shfsprite + (delta << 1); 1868 3351 else 1869 3352 sspr = NULL; 1870 - for (height = (short)var->height-1; height >= 0; height--) { 3353 + for (height = (short)var->height - 1; height >= 0; height--) { 1871 3354 bits = 0; words = delta; datawords = 0; 1872 - for (width = (short)var->width-1; width >= 0; width--) { 3355 + for (width = (short)var->width - 1; width >= 0; width--) { 1873 3356 if (bits == 0) { 1874 3357 bits = 16; --words; 1875 3358 #ifdef __mc68000__ 1876 3359 asm volatile ("movew %1@(%3:w:2),%0 ; swap %0 ; movew %1@+,%0" 1877 3360 : "=d" (datawords), "=a" (lspr) : "1" (lspr), "d" (delta)); 1878 3361 #else 1879 - datawords = (*(lspr+delta) << 16) | (*lspr++); 3362 + datawords = (*(lspr + delta) << 16) | (*lspr++); 1880 3363 #endif 1881 3364 } 1882 3365 --bits; ··· 1912 3395 return 0; 1913 3396 } 1914 3397 1915 - static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data) 3398 + static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, 3399 + u_char __user *data, struct amifb_par *par) 1916 3400 { 1917 - struct amifb_par *par = &currentpar; 1918 3401 register u_short *lspr, *sspr; 1919 3402 #ifdef __mc68000__ 1920 3403 register u_long datawords asm ("d2"); ··· 1939 3422 return -EINVAL; 1940 3423 if (!var->height) 1941 3424 return -EINVAL; 1942 - if (!access_ok(VERIFY_READ, data, var->width*var->height)) 3425 + if (!access_ok(VERIFY_READ, data, var->width * var->height)) 1943 3426 return -EFAULT; 1944 - delta = 1<<fmode; 3427 + delta = 1 << fmode; 1945 3428 lofsprite = shfsprite = (u_short *)spritememory; 1946 - lspr = lofsprite + (delta<<1); 3429 + lspr = lofsprite + (delta << 1); 1947 3430 if (par->bplcon0 & BPC0_LACE) { 1948 - if (((var->height+4)<<fmode<<2) > SPRITEMEMSIZE) 3431 + if (((var->height + 4) << fmode << 2) > SPRITEMEMSIZE) 1949 3432 return -EINVAL; 1950 - memset(lspr, 0, (var->height+4)<<fmode<<2); 1951 - shfsprite += ((var->height+5)&-2)<<fmode; 1952 - sspr = shfsprite + (delta<<1); 3433 + memset(lspr, 0, (var->height + 4) << fmode << 2); 3434 + shfsprite += ((var->height + 5)&-2) << fmode; 3435 + sspr = shfsprite + (delta << 1); 1953 3436 } else { 1954 - if (((var->height+2)<<fmode<<2) > SPRITEMEMSIZE) 3437 + if (((var->height + 2) << fmode << 2) > SPRITEMEMSIZE) 1955 3438 return -EINVAL; 1956 - memset(lspr, 0, (var->height+2)<<fmode<<2); 3439 + memset(lspr, 0, (var->height + 2) << fmode << 2); 1957 3440 sspr = NULL; 1958 3441 } 1959 - for (height = (short)var->height-1; height >= 0; height--) { 3442 + for (height = (short)var->height - 1; height >= 0; height--) { 1960 3443 bits = 16; words = delta; datawords = 0; 1961 - for (width = (short)var->width-1; width >= 0; width--) { 3444 + for (width = (short)var->width - 1; width >= 0; width--) { 1962 3445 unsigned long tdata = 0; 1963 3446 get_user(tdata, data); 1964 3447 data++; ··· 1971 3454 #else 1972 3455 datawords = ((datawords << 1) & 0xfffefffe); 1973 3456 datawords |= tdata & 1; 1974 - datawords |= (tdata & 2) << (16-1); 3457 + datawords |= (tdata & 2) << (16 - 1); 1975 3458 #endif 1976 3459 if (--bits == 0) { 1977 3460 bits = 16; --words; ··· 1979 3462 asm volatile ("swap %2 ; movew %2,%0@(%3:w:2) ; swap %2 ; movew %2,%0@+" 1980 3463 : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta)); 1981 3464 #else 1982 - *(lspr+delta) = (u_short) (datawords >> 16); 3465 + *(lspr + delta) = (u_short) (datawords >> 16); 1983 3466 *lspr++ = (u_short) (datawords & 0xffff); 1984 3467 #endif 1985 3468 } ··· 1992 3475 "swap %2 ; lslw %4,%2 ; movew %2,%0@+" 1993 3476 : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta), "d" (bits)); 1994 3477 #else 1995 - *(lspr+delta) = (u_short) (datawords >> (16+bits)); 3478 + *(lspr + delta) = (u_short) (datawords >> (16 + bits)); 1996 3479 *lspr++ = (u_short) ((datawords & 0x0000ffff) >> bits); 1997 3480 #endif 1998 3481 } ··· 2001 3484 asm volatile ("moveql #0,%%d0 ; movew %%d0,%0@(%2:w:2) ; movew %%d0,%0@+" 2002 3485 : "=a" (lspr) : "0" (lspr), "d" (delta) : "d0"); 2003 3486 #else 2004 - *(lspr+delta) = 0; 3487 + *(lspr + delta) = 0; 2005 3488 *lspr++ = 0; 2006 3489 #endif 2007 3490 } ··· 2030 3513 return 0; 2031 3514 } 2032 3515 2033 - static int ami_get_cursorstate(struct fb_cursorstate *state) 3516 + static int ami_get_cursorstate(struct fb_cursorstate *state, 3517 + const struct amifb_par *par) 2034 3518 { 2035 - struct amifb_par *par = &currentpar; 2036 - 2037 3519 state->xoffset = par->crsr.crsr_x; 2038 3520 state->yoffset = par->crsr.crsr_y; 2039 3521 state->mode = cursormode; 2040 3522 return 0; 2041 3523 } 2042 3524 2043 - static int ami_set_cursorstate(struct fb_cursorstate *state) 3525 + static int ami_set_cursorstate(struct fb_cursorstate *state, 3526 + struct amifb_par *par) 2044 3527 { 2045 - struct amifb_par *par = &currentpar; 2046 - 2047 3528 par->crsr.crsr_x = state->xoffset; 2048 3529 par->crsr.crsr_y = state->yoffset; 2049 3530 if ((cursormode = state->mode) == FB_CURSOR_OFF) ··· 2050 3535 return 0; 2051 3536 } 2052 3537 2053 - static void ami_set_sprite(void) 3538 + static void ami_set_sprite(const struct amifb_par *par) 2054 3539 { 2055 - struct amifb_par *par = &currentpar; 2056 3540 copins *copl, *cops; 2057 3541 u_short hs, vs, ve; 2058 3542 u_long pl, ps, pt; ··· 2060 3546 cops = copdisplay.list[currentcop][0]; 2061 3547 copl = copdisplay.list[currentcop][1]; 2062 3548 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; 3549 + mx = par->crsr.crsr_x - par->crsr.spot_x; 3550 + my = par->crsr.crsr_y - par->crsr.spot_y; 2065 3551 if (!(par->vmode & FB_VMODE_YWRAP)) { 2066 3552 mx -= par->xoffset; 2067 3553 my -= par->yoffset; ··· 2070 3556 mx > -(short)par->crsr.width && mx < par->xres && 2071 3557 my > -(short)par->crsr.height && my < par->yres) { 2072 3558 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); 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); 2076 3562 if (par->bplcon0 & BPC0_LACE) { 2077 3563 ps = ZTWO_PADDR(shfsprite); 2078 3564 lofsprite[0] = spr2hw_pos(vs, hs); 2079 - shfsprite[0] = spr2hw_pos(vs+1, hs); 3565 + shfsprite[0] = spr2hw_pos(vs + 1, hs); 2080 3566 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); 3567 + lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve); 3568 + shfsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs + 1, hs, ve + 1); 2083 3569 pt = pl; pl = ps; ps = pt; 2084 3570 } 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); 3571 + lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve + 1); 3572 + shfsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs + 1, hs, ve); 2087 3573 } 2088 3574 } else { 2089 3575 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); 3576 + lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve); 2091 3577 } 2092 3578 } 2093 3579 copl[cop_spr0ptrh].w[1] = highw(pl); ··· 2133 3619 custom.copjmp1 = 0; 2134 3620 } 2135 3621 2136 - static void ami_reinit_copper(void) 3622 + static void ami_reinit_copper(const struct amifb_par *par) 2137 3623 { 2138 - struct amifb_par *par = &currentpar; 2139 - 2140 3624 copdisplay.init[cip_bplcon0].w[1] = ~(BPC0_BPU3 | BPC0_BPU2 | BPC0_BPU1 | BPC0_BPU0) & par->bplcon0; 2141 - copdisplay.wait->l = CWAIT(32, par->diwstrt_v-4); 3625 + copdisplay.wait->l = CWAIT(32, par->diwstrt_v - 4); 2142 3626 } 3627 + 3628 + 3629 + /* 3630 + * Rebuild the Copper List 3631 + * 3632 + * We only change the things that are not static 3633 + */ 3634 + 3635 + static void ami_rebuild_copper(const struct amifb_par *par) 3636 + { 3637 + copins *copl, *cops; 3638 + u_short line, h_end1, h_end2; 3639 + short i; 3640 + u_long p; 3641 + 3642 + if (IS_AGA && maxfmode + par->clk_shift == 0) 3643 + h_end1 = par->diwstrt_h - 64; 3644 + else 3645 + h_end1 = par->htotal - 32; 3646 + h_end2 = par->ddfstop + 64; 3647 + 3648 + ami_set_sprite(par); 3649 + 3650 + copl = copdisplay.rebuild[1]; 3651 + p = par->bplpt0; 3652 + if (par->vmode & FB_VMODE_YWRAP) { 3653 + if ((par->vyres - par->yoffset) != 1 || !mod2(par->diwstrt_v)) { 3654 + if (par->yoffset > par->vyres - par->yres) { 3655 + for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) { 3656 + (copl++)->l = CMOVE(highw(p), bplpt[i]); 3657 + (copl++)->l = CMOVE2(loww(p), bplpt[i]); 3658 + } 3659 + line = par->diwstrt_v + ((par->vyres - par->yoffset) << par->line_shift) - 1; 3660 + while (line >= 512) { 3661 + (copl++)->l = CWAIT(h_end1, 510); 3662 + line -= 512; 3663 + } 3664 + if (line >= 510 && IS_AGA && maxfmode + par->clk_shift == 0) 3665 + (copl++)->l = CWAIT(h_end1, line); 3666 + else 3667 + (copl++)->l = CWAIT(h_end2, line); 3668 + p = par->bplpt0wrap; 3669 + } 3670 + } else 3671 + p = par->bplpt0wrap; 3672 + } 3673 + for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) { 3674 + (copl++)->l = CMOVE(highw(p), bplpt[i]); 3675 + (copl++)->l = CMOVE2(loww(p), bplpt[i]); 3676 + } 3677 + copl->l = CEND; 3678 + 3679 + if (par->bplcon0 & BPC0_LACE) { 3680 + cops = copdisplay.rebuild[0]; 3681 + p = par->bplpt0; 3682 + if (mod2(par->diwstrt_v)) 3683 + p -= par->next_line; 3684 + else 3685 + p += par->next_line; 3686 + if (par->vmode & FB_VMODE_YWRAP) { 3687 + if ((par->vyres - par->yoffset) != 1 || mod2(par->diwstrt_v)) { 3688 + if (par->yoffset > par->vyres - par->yres + 1) { 3689 + for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) { 3690 + (cops++)->l = CMOVE(highw(p), bplpt[i]); 3691 + (cops++)->l = CMOVE2(loww(p), bplpt[i]); 3692 + } 3693 + line = par->diwstrt_v + ((par->vyres - par->yoffset) << par->line_shift) - 2; 3694 + while (line >= 512) { 3695 + (cops++)->l = CWAIT(h_end1, 510); 3696 + line -= 512; 3697 + } 3698 + if (line > 510 && IS_AGA && maxfmode + par->clk_shift == 0) 3699 + (cops++)->l = CWAIT(h_end1, line); 3700 + else 3701 + (cops++)->l = CWAIT(h_end2, line); 3702 + p = par->bplpt0wrap; 3703 + if (mod2(par->diwstrt_v + par->vyres - 3704 + par->yoffset)) 3705 + p -= par->next_line; 3706 + else 3707 + p += par->next_line; 3708 + } 3709 + } else 3710 + p = par->bplpt0wrap - par->next_line; 3711 + } 3712 + for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) { 3713 + (cops++)->l = CMOVE(highw(p), bplpt[i]); 3714 + (cops++)->l = CMOVE2(loww(p), bplpt[i]); 3715 + } 3716 + cops->l = CEND; 3717 + } 3718 + } 3719 + 2143 3720 2144 3721 /* 2145 3722 * Build the Copper List 2146 3723 */ 2147 3724 2148 - static void ami_build_copper(void) 3725 + static void ami_build_copper(struct fb_info *info) 2149 3726 { 2150 - struct amifb_par *par = &currentpar; 3727 + struct amifb_par *par = info->par; 2151 3728 copins *copl, *cops; 2152 3729 u_long p; 2153 3730 ··· 2259 3654 (cops++)->l = CMOVE(0, sprpt[0]); 2260 3655 (cops++)->l = CMOVE2(0, sprpt[0]); 2261 3656 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); 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); 2264 3659 (cops++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt); 2265 3660 (cops++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop); 2266 3661 if (!IS_OCS) { 2267 - (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v+1, 2268 - par->diwstop_h, par->diwstop_v+1), diwhigh); 3662 + (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v + 1, 3663 + par->diwstop_h, par->diwstop_v + 1), diwhigh); 2269 3664 (cops++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v, 2270 - par->diwstop_h, par->diwstop_v), diwhigh); 3665 + par->diwstop_h, par->diwstop_v), diwhigh); 2271 3666 #if 0 2272 3667 if (par->beamcon0 & BMC0_VARBEAMEN) { 2273 3668 (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); 3669 + (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt + 1), vbstrt); 3670 + (copl++)->l = CMOVE(vbstop2hw(par->vbstop + 1), vbstop); 2276 3671 (cops++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal); 2277 3672 (cops++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt); 2278 3673 (cops++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop); ··· 2291 3686 (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop); 2292 3687 if (!IS_OCS) { 2293 3688 (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v, 2294 - par->diwstop_h, par->diwstop_v), diwhigh); 3689 + par->diwstop_h, par->diwstop_v), diwhigh); 2295 3690 #if 0 2296 3691 if (par->beamcon0 & BMC0_VARBEAMEN) { 2297 3692 (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal); ··· 2303 3698 } 2304 3699 copdisplay.rebuild[1] = copl; 2305 3700 2306 - ami_update_par(); 2307 - ami_rebuild_copper(); 3701 + ami_update_par(info); 3702 + ami_rebuild_copper(info->par); 3703 + } 3704 + 3705 + 3706 + static void __init amifb_setup_mcap(char *spec) 3707 + { 3708 + char *p; 3709 + int vmin, vmax, hmin, hmax; 3710 + 3711 + /* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax> 3712 + * <V*> vertical freq. in Hz 3713 + * <H*> horizontal freq. in kHz 3714 + */ 3715 + 3716 + if (!(p = strsep(&spec, ";")) || !*p) 3717 + return; 3718 + vmin = simple_strtoul(p, NULL, 10); 3719 + if (vmin <= 0) 3720 + return; 3721 + if (!(p = strsep(&spec, ";")) || !*p) 3722 + return; 3723 + vmax = simple_strtoul(p, NULL, 10); 3724 + if (vmax <= 0 || vmax <= vmin) 3725 + return; 3726 + if (!(p = strsep(&spec, ";")) || !*p) 3727 + return; 3728 + hmin = 1000 * simple_strtoul(p, NULL, 10); 3729 + if (hmin <= 0) 3730 + return; 3731 + if (!(p = strsep(&spec, "")) || !*p) 3732 + return; 3733 + hmax = 1000 * simple_strtoul(p, NULL, 10); 3734 + if (hmax <= 0 || hmax <= hmin) 3735 + return; 3736 + 3737 + amifb_hfmin = hmin; 3738 + amifb_hfmax = hmax; 3739 + amifb_vfmin = vmin; 3740 + amifb_vfmax = vmax; 3741 + } 3742 + 3743 + static int __init amifb_setup(char *options) 3744 + { 3745 + char *this_opt; 3746 + 3747 + if (!options || !*options) 3748 + return 0; 3749 + 3750 + while ((this_opt = strsep(&options, ",")) != NULL) { 3751 + if (!*this_opt) 3752 + continue; 3753 + if (!strcmp(this_opt, "inverse")) { 3754 + amifb_inverse = 1; 3755 + fb_invert_cmaps(); 3756 + } else if (!strcmp(this_opt, "ilbm")) 3757 + amifb_ilbm = 1; 3758 + else if (!strncmp(this_opt, "monitorcap:", 11)) 3759 + amifb_setup_mcap(this_opt + 11); 3760 + else if (!strncmp(this_opt, "fstart:", 7)) 3761 + min_fstrt = simple_strtoul(this_opt + 7, NULL, 0); 3762 + else 3763 + mode_option = this_opt; 3764 + } 3765 + 3766 + if (min_fstrt < 48) 3767 + min_fstrt = 48; 3768 + 3769 + return 0; 3770 + } 3771 + 3772 + 3773 + static int amifb_check_var(struct fb_var_screeninfo *var, 3774 + struct fb_info *info) 3775 + { 3776 + int err; 3777 + struct amifb_par par; 3778 + 3779 + /* Validate wanted screen parameters */ 3780 + err = ami_decode_var(var, &par, info); 3781 + if (err) 3782 + return err; 3783 + 3784 + /* Encode (possibly rounded) screen parameters */ 3785 + ami_encode_var(var, &par); 3786 + return 0; 3787 + } 3788 + 3789 + 3790 + static int amifb_set_par(struct fb_info *info) 3791 + { 3792 + struct amifb_par *par = info->par; 3793 + int error; 3794 + 3795 + do_vmode_pan = 0; 3796 + do_vmode_full = 0; 3797 + 3798 + /* Decode wanted screen parameters */ 3799 + error = ami_decode_var(&info->var, par, info); 3800 + if (error) 3801 + return error; 3802 + 3803 + /* Set new videomode */ 3804 + ami_build_copper(info); 3805 + 3806 + /* Set VBlank trigger */ 3807 + do_vmode_full = 1; 3808 + 3809 + /* Update fix for new screen parameters */ 3810 + if (par->bpp == 1) { 3811 + info->fix.type = FB_TYPE_PACKED_PIXELS; 3812 + info->fix.type_aux = 0; 3813 + } else if (amifb_ilbm) { 3814 + info->fix.type = FB_TYPE_INTERLEAVED_PLANES; 3815 + info->fix.type_aux = par->next_line; 3816 + } else { 3817 + info->fix.type = FB_TYPE_PLANES; 3818 + info->fix.type_aux = 0; 3819 + } 3820 + info->fix.line_length = div8(upx(16 << maxfmode, par->vxres)); 3821 + 3822 + if (par->vmode & FB_VMODE_YWRAP) { 3823 + info->fix.ywrapstep = 1; 3824 + info->fix.xpanstep = 0; 3825 + info->fix.ypanstep = 0; 3826 + info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YWRAP | 3827 + FBINFO_READS_FAST; /* override SCROLL_REDRAW */ 3828 + } else { 3829 + info->fix.ywrapstep = 0; 3830 + if (par->vmode & FB_VMODE_SMOOTH_XPAN) 3831 + info->fix.xpanstep = 1; 3832 + else 3833 + info->fix.xpanstep = 16 << maxfmode; 3834 + info->fix.ypanstep = 1; 3835 + info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; 3836 + } 3837 + return 0; 3838 + } 3839 + 3840 + 3841 + /* 3842 + * Set a single color register. The values supplied are already 3843 + * rounded down to the hardware's capabilities (according to the 3844 + * entries in the var structure). Return != 0 for invalid regno. 3845 + */ 3846 + 3847 + static int amifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, 3848 + u_int transp, struct fb_info *info) 3849 + { 3850 + const struct amifb_par *par = info->par; 3851 + 3852 + if (IS_AGA) { 3853 + if (regno > 255) 3854 + return 1; 3855 + } else if (par->bplcon0 & BPC0_SHRES) { 3856 + if (regno > 3) 3857 + return 1; 3858 + } else { 3859 + if (regno > 31) 3860 + return 1; 3861 + } 3862 + red >>= 8; 3863 + green >>= 8; 3864 + blue >>= 8; 3865 + if (!regno) { 3866 + red0 = red; 3867 + green0 = green; 3868 + blue0 = blue; 3869 + } 3870 + 3871 + /* 3872 + * Update the corresponding Hardware Color Register, unless it's Color 3873 + * Register 0 and the screen is blanked. 3874 + * 3875 + * VBlank is switched off to protect bplcon3 or ecs_palette[] from 3876 + * being changed by ami_do_blank() during the VBlank. 3877 + */ 3878 + 3879 + if (regno || !is_blanked) { 3880 + #if defined(CONFIG_FB_AMIGA_AGA) 3881 + if (IS_AGA) { 3882 + u_short bplcon3 = par->bplcon3; 3883 + VBlankOff(); 3884 + custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000); 3885 + custom.color[regno & 31] = rgb2hw8_high(red, green, 3886 + blue); 3887 + custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000) | 3888 + BPC3_LOCT; 3889 + custom.color[regno & 31] = rgb2hw8_low(red, green, 3890 + blue); 3891 + custom.bplcon3 = bplcon3; 3892 + VBlankOn(); 3893 + } else 3894 + #endif 3895 + #if defined(CONFIG_FB_AMIGA_ECS) 3896 + if (par->bplcon0 & BPC0_SHRES) { 3897 + u_short color, mask; 3898 + int i; 3899 + 3900 + mask = 0x3333; 3901 + color = rgb2hw2(red, green, blue); 3902 + VBlankOff(); 3903 + for (i = regno + 12; i >= (int)regno; i -= 4) 3904 + custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color; 3905 + mask <<= 2; color >>= 2; 3906 + regno = down16(regno) + mul4(mod4(regno)); 3907 + for (i = regno + 3; i >= (int)regno; i--) 3908 + custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color; 3909 + VBlankOn(); 3910 + } else 3911 + #endif 3912 + custom.color[regno] = rgb2hw4(red, green, blue); 3913 + } 3914 + return 0; 3915 + } 3916 + 3917 + 3918 + /* 3919 + * Blank the display. 3920 + */ 3921 + 3922 + static int amifb_blank(int blank, struct fb_info *info) 3923 + { 3924 + do_blank = blank ? blank : -1; 3925 + 3926 + return 0; 3927 + } 3928 + 3929 + 3930 + /* 3931 + * Pan or Wrap the Display 3932 + * 3933 + * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag 3934 + */ 3935 + 3936 + static int amifb_pan_display(struct fb_var_screeninfo *var, 3937 + struct fb_info *info) 3938 + { 3939 + if (var->vmode & FB_VMODE_YWRAP) { 3940 + if (var->yoffset < 0 || 3941 + var->yoffset >= info->var.yres_virtual || var->xoffset) 3942 + return -EINVAL; 3943 + } else { 3944 + /* 3945 + * TODO: There will be problems when xpan!=1, so some columns 3946 + * on the right side will never be seen 3947 + */ 3948 + if (var->xoffset + info->var.xres > 3949 + upx(16 << maxfmode, info->var.xres_virtual) || 3950 + var->yoffset + info->var.yres > info->var.yres_virtual) 3951 + return -EINVAL; 3952 + } 3953 + ami_pan_var(var, info); 3954 + info->var.xoffset = var->xoffset; 3955 + info->var.yoffset = var->yoffset; 3956 + if (var->vmode & FB_VMODE_YWRAP) 3957 + info->var.vmode |= FB_VMODE_YWRAP; 3958 + else 3959 + info->var.vmode &= ~FB_VMODE_YWRAP; 3960 + return 0; 3961 + } 3962 + 3963 + 3964 + #if BITS_PER_LONG == 32 3965 + #define BYTES_PER_LONG 4 3966 + #define SHIFT_PER_LONG 5 3967 + #elif BITS_PER_LONG == 64 3968 + #define BYTES_PER_LONG 8 3969 + #define SHIFT_PER_LONG 6 3970 + #else 3971 + #define Please update me 3972 + #endif 3973 + 3974 + 3975 + /* 3976 + * Compose two values, using a bitmask as decision value 3977 + * This is equivalent to (a & mask) | (b & ~mask) 3978 + */ 3979 + 3980 + static inline unsigned long comp(unsigned long a, unsigned long b, 3981 + unsigned long mask) 3982 + { 3983 + return ((a ^ b) & mask) ^ b; 3984 + } 3985 + 3986 + 3987 + static inline unsigned long xor(unsigned long a, unsigned long b, 3988 + unsigned long mask) 3989 + { 3990 + return (a & mask) ^ b; 3991 + } 3992 + 3993 + 3994 + /* 3995 + * Unaligned forward bit copy using 32-bit or 64-bit memory accesses 3996 + */ 3997 + 3998 + static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src, 3999 + int src_idx, u32 n) 4000 + { 4001 + unsigned long first, last; 4002 + int shift = dst_idx - src_idx, left, right; 4003 + unsigned long d0, d1; 4004 + int m; 4005 + 4006 + if (!n) 4007 + return; 4008 + 4009 + shift = dst_idx - src_idx; 4010 + first = ~0UL >> dst_idx; 4011 + last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG)); 4012 + 4013 + if (!shift) { 4014 + // Same alignment for source and dest 4015 + 4016 + if (dst_idx + n <= BITS_PER_LONG) { 4017 + // Single word 4018 + if (last) 4019 + first &= last; 4020 + *dst = comp(*src, *dst, first); 4021 + } else { 4022 + // Multiple destination words 4023 + // Leading bits 4024 + if (first) { 4025 + *dst = comp(*src, *dst, first); 4026 + dst++; 4027 + src++; 4028 + n -= BITS_PER_LONG - dst_idx; 4029 + } 4030 + 4031 + // Main chunk 4032 + n /= BITS_PER_LONG; 4033 + while (n >= 8) { 4034 + *dst++ = *src++; 4035 + *dst++ = *src++; 4036 + *dst++ = *src++; 4037 + *dst++ = *src++; 4038 + *dst++ = *src++; 4039 + *dst++ = *src++; 4040 + *dst++ = *src++; 4041 + *dst++ = *src++; 4042 + n -= 8; 4043 + } 4044 + while (n--) 4045 + *dst++ = *src++; 4046 + 4047 + // Trailing bits 4048 + if (last) 4049 + *dst = comp(*src, *dst, last); 4050 + } 4051 + } else { 4052 + // Different alignment for source and dest 4053 + 4054 + right = shift & (BITS_PER_LONG - 1); 4055 + left = -shift & (BITS_PER_LONG - 1); 4056 + 4057 + if (dst_idx + n <= BITS_PER_LONG) { 4058 + // Single destination word 4059 + if (last) 4060 + first &= last; 4061 + if (shift > 0) { 4062 + // Single source word 4063 + *dst = comp(*src >> right, *dst, first); 4064 + } else if (src_idx + n <= BITS_PER_LONG) { 4065 + // Single source word 4066 + *dst = comp(*src << left, *dst, first); 4067 + } else { 4068 + // 2 source words 4069 + d0 = *src++; 4070 + d1 = *src; 4071 + *dst = comp(d0 << left | d1 >> right, *dst, 4072 + first); 4073 + } 4074 + } else { 4075 + // Multiple destination words 4076 + d0 = *src++; 4077 + // Leading bits 4078 + if (shift > 0) { 4079 + // Single source word 4080 + *dst = comp(d0 >> right, *dst, first); 4081 + dst++; 4082 + n -= BITS_PER_LONG - dst_idx; 4083 + } else { 4084 + // 2 source words 4085 + d1 = *src++; 4086 + *dst = comp(d0 << left | d1 >> right, *dst, 4087 + first); 4088 + d0 = d1; 4089 + dst++; 4090 + n -= BITS_PER_LONG - dst_idx; 4091 + } 4092 + 4093 + // Main chunk 4094 + m = n % BITS_PER_LONG; 4095 + n /= BITS_PER_LONG; 4096 + while (n >= 4) { 4097 + d1 = *src++; 4098 + *dst++ = d0 << left | d1 >> right; 4099 + d0 = d1; 4100 + d1 = *src++; 4101 + *dst++ = d0 << left | d1 >> right; 4102 + d0 = d1; 4103 + d1 = *src++; 4104 + *dst++ = d0 << left | d1 >> right; 4105 + d0 = d1; 4106 + d1 = *src++; 4107 + *dst++ = d0 << left | d1 >> right; 4108 + d0 = d1; 4109 + n -= 4; 4110 + } 4111 + while (n--) { 4112 + d1 = *src++; 4113 + *dst++ = d0 << left | d1 >> right; 4114 + d0 = d1; 4115 + } 4116 + 4117 + // Trailing bits 4118 + if (last) { 4119 + if (m <= right) { 4120 + // Single source word 4121 + *dst = comp(d0 << left, *dst, last); 4122 + } else { 4123 + // 2 source words 4124 + d1 = *src; 4125 + *dst = comp(d0 << left | d1 >> right, 4126 + *dst, last); 4127 + } 4128 + } 4129 + } 4130 + } 4131 + } 4132 + 4133 + 4134 + /* 4135 + * Unaligned reverse bit copy using 32-bit or 64-bit memory accesses 4136 + */ 4137 + 4138 + static void bitcpy_rev(unsigned long *dst, int dst_idx, 4139 + const unsigned long *src, int src_idx, u32 n) 4140 + { 4141 + unsigned long first, last; 4142 + int shift = dst_idx - src_idx, left, right; 4143 + unsigned long d0, d1; 4144 + int m; 4145 + 4146 + if (!n) 4147 + return; 4148 + 4149 + dst += (n - 1) / BITS_PER_LONG; 4150 + src += (n - 1) / BITS_PER_LONG; 4151 + if ((n - 1) % BITS_PER_LONG) { 4152 + dst_idx += (n - 1) % BITS_PER_LONG; 4153 + dst += dst_idx >> SHIFT_PER_LONG; 4154 + dst_idx &= BITS_PER_LONG - 1; 4155 + src_idx += (n - 1) % BITS_PER_LONG; 4156 + src += src_idx >> SHIFT_PER_LONG; 4157 + src_idx &= BITS_PER_LONG - 1; 4158 + } 4159 + 4160 + shift = dst_idx - src_idx; 4161 + first = ~0UL << (BITS_PER_LONG - 1 - dst_idx); 4162 + last = ~(~0UL << (BITS_PER_LONG - 1 - ((dst_idx - n) % BITS_PER_LONG))); 4163 + 4164 + if (!shift) { 4165 + // Same alignment for source and dest 4166 + 4167 + if ((unsigned long)dst_idx + 1 >= n) { 4168 + // Single word 4169 + if (last) 4170 + first &= last; 4171 + *dst = comp(*src, *dst, first); 4172 + } else { 4173 + // Multiple destination words 4174 + // Leading bits 4175 + if (first) { 4176 + *dst = comp(*src, *dst, first); 4177 + dst--; 4178 + src--; 4179 + n -= dst_idx + 1; 4180 + } 4181 + 4182 + // Main chunk 4183 + n /= BITS_PER_LONG; 4184 + while (n >= 8) { 4185 + *dst-- = *src--; 4186 + *dst-- = *src--; 4187 + *dst-- = *src--; 4188 + *dst-- = *src--; 4189 + *dst-- = *src--; 4190 + *dst-- = *src--; 4191 + *dst-- = *src--; 4192 + *dst-- = *src--; 4193 + n -= 8; 4194 + } 4195 + while (n--) 4196 + *dst-- = *src--; 4197 + 4198 + // Trailing bits 4199 + if (last) 4200 + *dst = comp(*src, *dst, last); 4201 + } 4202 + } else { 4203 + // Different alignment for source and dest 4204 + 4205 + right = shift & (BITS_PER_LONG - 1); 4206 + left = -shift & (BITS_PER_LONG - 1); 4207 + 4208 + if ((unsigned long)dst_idx + 1 >= n) { 4209 + // Single destination word 4210 + if (last) 4211 + first &= last; 4212 + if (shift < 0) { 4213 + // Single source word 4214 + *dst = comp(*src << left, *dst, first); 4215 + } else if (1 + (unsigned long)src_idx >= n) { 4216 + // Single source word 4217 + *dst = comp(*src >> right, *dst, first); 4218 + } else { 4219 + // 2 source words 4220 + d0 = *src--; 4221 + d1 = *src; 4222 + *dst = comp(d0 >> right | d1 << left, *dst, 4223 + first); 4224 + } 4225 + } else { 4226 + // Multiple destination words 4227 + d0 = *src--; 4228 + // Leading bits 4229 + if (shift < 0) { 4230 + // Single source word 4231 + *dst = comp(d0 << left, *dst, first); 4232 + dst--; 4233 + n -= dst_idx + 1; 4234 + } else { 4235 + // 2 source words 4236 + d1 = *src--; 4237 + *dst = comp(d0 >> right | d1 << left, *dst, 4238 + first); 4239 + d0 = d1; 4240 + dst--; 4241 + n -= dst_idx + 1; 4242 + } 4243 + 4244 + // Main chunk 4245 + m = n % BITS_PER_LONG; 4246 + n /= BITS_PER_LONG; 4247 + while (n >= 4) { 4248 + d1 = *src--; 4249 + *dst-- = d0 >> right | d1 << left; 4250 + d0 = d1; 4251 + d1 = *src--; 4252 + *dst-- = d0 >> right | d1 << left; 4253 + d0 = d1; 4254 + d1 = *src--; 4255 + *dst-- = d0 >> right | d1 << left; 4256 + d0 = d1; 4257 + d1 = *src--; 4258 + *dst-- = d0 >> right | d1 << left; 4259 + d0 = d1; 4260 + n -= 4; 4261 + } 4262 + while (n--) { 4263 + d1 = *src--; 4264 + *dst-- = d0 >> right | d1 << left; 4265 + d0 = d1; 4266 + } 4267 + 4268 + // Trailing bits 4269 + if (last) { 4270 + if (m <= left) { 4271 + // Single source word 4272 + *dst = comp(d0 >> right, *dst, last); 4273 + } else { 4274 + // 2 source words 4275 + d1 = *src; 4276 + *dst = comp(d0 >> right | d1 << left, 4277 + *dst, last); 4278 + } 4279 + } 4280 + } 4281 + } 4282 + } 4283 + 4284 + 4285 + /* 4286 + * Unaligned forward inverting bit copy using 32-bit or 64-bit memory 4287 + * accesses 4288 + */ 4289 + 4290 + static void bitcpy_not(unsigned long *dst, int dst_idx, 4291 + const unsigned long *src, int src_idx, u32 n) 4292 + { 4293 + unsigned long first, last; 4294 + int shift = dst_idx - src_idx, left, right; 4295 + unsigned long d0, d1; 4296 + int m; 4297 + 4298 + if (!n) 4299 + return; 4300 + 4301 + shift = dst_idx - src_idx; 4302 + first = ~0UL >> dst_idx; 4303 + last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG)); 4304 + 4305 + if (!shift) { 4306 + // Same alignment for source and dest 4307 + 4308 + if (dst_idx + n <= BITS_PER_LONG) { 4309 + // Single word 4310 + if (last) 4311 + first &= last; 4312 + *dst = comp(~*src, *dst, first); 4313 + } else { 4314 + // Multiple destination words 4315 + // Leading bits 4316 + if (first) { 4317 + *dst = comp(~*src, *dst, first); 4318 + dst++; 4319 + src++; 4320 + n -= BITS_PER_LONG - dst_idx; 4321 + } 4322 + 4323 + // Main chunk 4324 + n /= BITS_PER_LONG; 4325 + while (n >= 8) { 4326 + *dst++ = ~*src++; 4327 + *dst++ = ~*src++; 4328 + *dst++ = ~*src++; 4329 + *dst++ = ~*src++; 4330 + *dst++ = ~*src++; 4331 + *dst++ = ~*src++; 4332 + *dst++ = ~*src++; 4333 + *dst++ = ~*src++; 4334 + n -= 8; 4335 + } 4336 + while (n--) 4337 + *dst++ = ~*src++; 4338 + 4339 + // Trailing bits 4340 + if (last) 4341 + *dst = comp(~*src, *dst, last); 4342 + } 4343 + } else { 4344 + // Different alignment for source and dest 4345 + 4346 + right = shift & (BITS_PER_LONG - 1); 4347 + left = -shift & (BITS_PER_LONG - 1); 4348 + 4349 + if (dst_idx + n <= BITS_PER_LONG) { 4350 + // Single destination word 4351 + if (last) 4352 + first &= last; 4353 + if (shift > 0) { 4354 + // Single source word 4355 + *dst = comp(~*src >> right, *dst, first); 4356 + } else if (src_idx + n <= BITS_PER_LONG) { 4357 + // Single source word 4358 + *dst = comp(~*src << left, *dst, first); 4359 + } else { 4360 + // 2 source words 4361 + d0 = ~*src++; 4362 + d1 = ~*src; 4363 + *dst = comp(d0 << left | d1 >> right, *dst, 4364 + first); 4365 + } 4366 + } else { 4367 + // Multiple destination words 4368 + d0 = ~*src++; 4369 + // Leading bits 4370 + if (shift > 0) { 4371 + // Single source word 4372 + *dst = comp(d0 >> right, *dst, first); 4373 + dst++; 4374 + n -= BITS_PER_LONG - dst_idx; 4375 + } else { 4376 + // 2 source words 4377 + d1 = ~*src++; 4378 + *dst = comp(d0 << left | d1 >> right, *dst, 4379 + first); 4380 + d0 = d1; 4381 + dst++; 4382 + n -= BITS_PER_LONG - dst_idx; 4383 + } 4384 + 4385 + // Main chunk 4386 + m = n % BITS_PER_LONG; 4387 + n /= BITS_PER_LONG; 4388 + while (n >= 4) { 4389 + d1 = ~*src++; 4390 + *dst++ = d0 << left | d1 >> right; 4391 + d0 = d1; 4392 + d1 = ~*src++; 4393 + *dst++ = d0 << left | d1 >> right; 4394 + d0 = d1; 4395 + d1 = ~*src++; 4396 + *dst++ = d0 << left | d1 >> right; 4397 + d0 = d1; 4398 + d1 = ~*src++; 4399 + *dst++ = d0 << left | d1 >> right; 4400 + d0 = d1; 4401 + n -= 4; 4402 + } 4403 + while (n--) { 4404 + d1 = ~*src++; 4405 + *dst++ = d0 << left | d1 >> right; 4406 + d0 = d1; 4407 + } 4408 + 4409 + // Trailing bits 4410 + if (last) { 4411 + if (m <= right) { 4412 + // Single source word 4413 + *dst = comp(d0 << left, *dst, last); 4414 + } else { 4415 + // 2 source words 4416 + d1 = ~*src; 4417 + *dst = comp(d0 << left | d1 >> right, 4418 + *dst, last); 4419 + } 4420 + } 4421 + } 4422 + } 4423 + } 4424 + 4425 + 4426 + /* 4427 + * Unaligned 32-bit pattern fill using 32/64-bit memory accesses 4428 + */ 4429 + 4430 + static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n) 4431 + { 4432 + unsigned long val = pat; 4433 + unsigned long first, last; 4434 + 4435 + if (!n) 4436 + return; 4437 + 4438 + #if BITS_PER_LONG == 64 4439 + val |= val << 32; 4440 + #endif 4441 + 4442 + first = ~0UL >> dst_idx; 4443 + last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG)); 4444 + 4445 + if (dst_idx + n <= BITS_PER_LONG) { 4446 + // Single word 4447 + if (last) 4448 + first &= last; 4449 + *dst = comp(val, *dst, first); 4450 + } else { 4451 + // Multiple destination words 4452 + // Leading bits 4453 + if (first) { 4454 + *dst = comp(val, *dst, first); 4455 + dst++; 4456 + n -= BITS_PER_LONG - dst_idx; 4457 + } 4458 + 4459 + // Main chunk 4460 + n /= BITS_PER_LONG; 4461 + while (n >= 8) { 4462 + *dst++ = val; 4463 + *dst++ = val; 4464 + *dst++ = val; 4465 + *dst++ = val; 4466 + *dst++ = val; 4467 + *dst++ = val; 4468 + *dst++ = val; 4469 + *dst++ = val; 4470 + n -= 8; 4471 + } 4472 + while (n--) 4473 + *dst++ = val; 4474 + 4475 + // Trailing bits 4476 + if (last) 4477 + *dst = comp(val, *dst, last); 4478 + } 4479 + } 4480 + 4481 + 4482 + /* 4483 + * Unaligned 32-bit pattern xor using 32/64-bit memory accesses 4484 + */ 4485 + 4486 + static void bitxor32(unsigned long *dst, int dst_idx, u32 pat, u32 n) 4487 + { 4488 + unsigned long val = pat; 4489 + unsigned long first, last; 4490 + 4491 + if (!n) 4492 + return; 4493 + 4494 + #if BITS_PER_LONG == 64 4495 + val |= val << 32; 4496 + #endif 4497 + 4498 + first = ~0UL >> dst_idx; 4499 + last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG)); 4500 + 4501 + if (dst_idx + n <= BITS_PER_LONG) { 4502 + // Single word 4503 + if (last) 4504 + first &= last; 4505 + *dst = xor(val, *dst, first); 4506 + } else { 4507 + // Multiple destination words 4508 + // Leading bits 4509 + if (first) { 4510 + *dst = xor(val, *dst, first); 4511 + dst++; 4512 + n -= BITS_PER_LONG - dst_idx; 4513 + } 4514 + 4515 + // Main chunk 4516 + n /= BITS_PER_LONG; 4517 + while (n >= 4) { 4518 + *dst++ ^= val; 4519 + *dst++ ^= val; 4520 + *dst++ ^= val; 4521 + *dst++ ^= val; 4522 + n -= 4; 4523 + } 4524 + while (n--) 4525 + *dst++ ^= val; 4526 + 4527 + // Trailing bits 4528 + if (last) 4529 + *dst = xor(val, *dst, last); 4530 + } 4531 + } 4532 + 4533 + static inline void fill_one_line(int bpp, unsigned long next_plane, 4534 + unsigned long *dst, int dst_idx, u32 n, 4535 + u32 color) 4536 + { 4537 + while (1) { 4538 + dst += dst_idx >> SHIFT_PER_LONG; 4539 + dst_idx &= (BITS_PER_LONG - 1); 4540 + bitfill32(dst, dst_idx, color & 1 ? ~0 : 0, n); 4541 + if (!--bpp) 4542 + break; 4543 + color >>= 1; 4544 + dst_idx += next_plane * 8; 4545 + } 4546 + } 4547 + 4548 + static inline void xor_one_line(int bpp, unsigned long next_plane, 4549 + unsigned long *dst, int dst_idx, u32 n, 4550 + u32 color) 4551 + { 4552 + while (color) { 4553 + dst += dst_idx >> SHIFT_PER_LONG; 4554 + dst_idx &= (BITS_PER_LONG - 1); 4555 + bitxor32(dst, dst_idx, color & 1 ? ~0 : 0, n); 4556 + if (!--bpp) 4557 + break; 4558 + color >>= 1; 4559 + dst_idx += next_plane * 8; 4560 + } 4561 + } 4562 + 4563 + 4564 + static void amifb_fillrect(struct fb_info *info, 4565 + const struct fb_fillrect *rect) 4566 + { 4567 + struct amifb_par *par = info->par; 4568 + int dst_idx, x2, y2; 4569 + unsigned long *dst; 4570 + u32 width, height; 4571 + 4572 + if (!rect->width || !rect->height) 4573 + return; 4574 + 4575 + /* 4576 + * We could use hardware clipping but on many cards you get around 4577 + * hardware clipping by writing to framebuffer directly. 4578 + * */ 4579 + x2 = rect->dx + rect->width; 4580 + y2 = rect->dy + rect->height; 4581 + x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual; 4582 + y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual; 4583 + width = x2 - rect->dx; 4584 + height = y2 - rect->dy; 4585 + 4586 + dst = (unsigned long *) 4587 + ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1)); 4588 + dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8; 4589 + dst_idx += rect->dy * par->next_line * 8 + rect->dx; 4590 + while (height--) { 4591 + switch (rect->rop) { 4592 + case ROP_COPY: 4593 + fill_one_line(info->var.bits_per_pixel, 4594 + par->next_plane, dst, dst_idx, width, 4595 + rect->color); 4596 + break; 4597 + 4598 + case ROP_XOR: 4599 + xor_one_line(info->var.bits_per_pixel, par->next_plane, 4600 + dst, dst_idx, width, rect->color); 4601 + break; 4602 + } 4603 + dst_idx += par->next_line * 8; 4604 + } 4605 + } 4606 + 4607 + static inline void copy_one_line(int bpp, unsigned long next_plane, 4608 + unsigned long *dst, int dst_idx, 4609 + unsigned long *src, int src_idx, u32 n) 4610 + { 4611 + while (1) { 4612 + dst += dst_idx >> SHIFT_PER_LONG; 4613 + dst_idx &= (BITS_PER_LONG - 1); 4614 + src += src_idx >> SHIFT_PER_LONG; 4615 + src_idx &= (BITS_PER_LONG - 1); 4616 + bitcpy(dst, dst_idx, src, src_idx, n); 4617 + if (!--bpp) 4618 + break; 4619 + dst_idx += next_plane * 8; 4620 + src_idx += next_plane * 8; 4621 + } 4622 + } 4623 + 4624 + static inline void copy_one_line_rev(int bpp, unsigned long next_plane, 4625 + unsigned long *dst, int dst_idx, 4626 + unsigned long *src, int src_idx, u32 n) 4627 + { 4628 + while (1) { 4629 + dst += dst_idx >> SHIFT_PER_LONG; 4630 + dst_idx &= (BITS_PER_LONG - 1); 4631 + src += src_idx >> SHIFT_PER_LONG; 4632 + src_idx &= (BITS_PER_LONG - 1); 4633 + bitcpy_rev(dst, dst_idx, src, src_idx, n); 4634 + if (!--bpp) 4635 + break; 4636 + dst_idx += next_plane * 8; 4637 + src_idx += next_plane * 8; 4638 + } 4639 + } 4640 + 4641 + 4642 + static void amifb_copyarea(struct fb_info *info, 4643 + const struct fb_copyarea *area) 4644 + { 4645 + struct amifb_par *par = info->par; 4646 + int x2, y2; 4647 + u32 dx, dy, sx, sy, width, height; 4648 + unsigned long *dst, *src; 4649 + int dst_idx, src_idx; 4650 + int rev_copy = 0; 4651 + 4652 + /* clip the destination */ 4653 + x2 = area->dx + area->width; 4654 + y2 = area->dy + area->height; 4655 + dx = area->dx > 0 ? area->dx : 0; 4656 + dy = area->dy > 0 ? area->dy : 0; 4657 + x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual; 4658 + y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual; 4659 + width = x2 - dx; 4660 + height = y2 - dy; 4661 + 4662 + if (area->sx + dx < area->dx || area->sy + dy < area->dy) 4663 + return; 4664 + 4665 + /* update sx,sy */ 4666 + sx = area->sx + (dx - area->dx); 4667 + sy = area->sy + (dy - area->dy); 4668 + 4669 + /* the source must be completely inside the virtual screen */ 4670 + if (sx + width > info->var.xres_virtual || 4671 + sy + height > info->var.yres_virtual) 4672 + return; 4673 + 4674 + if (dy > sy || (dy == sy && dx > sx)) { 4675 + dy += height; 4676 + sy += height; 4677 + rev_copy = 1; 4678 + } 4679 + dst = (unsigned long *) 4680 + ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1)); 4681 + src = dst; 4682 + dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8; 4683 + src_idx = dst_idx; 4684 + dst_idx += dy * par->next_line * 8 + dx; 4685 + src_idx += sy * par->next_line * 8 + sx; 4686 + if (rev_copy) { 4687 + while (height--) { 4688 + dst_idx -= par->next_line * 8; 4689 + src_idx -= par->next_line * 8; 4690 + copy_one_line_rev(info->var.bits_per_pixel, 4691 + par->next_plane, dst, dst_idx, src, 4692 + src_idx, width); 4693 + } 4694 + } else { 4695 + while (height--) { 4696 + copy_one_line(info->var.bits_per_pixel, 4697 + par->next_plane, dst, dst_idx, src, 4698 + src_idx, width); 4699 + dst_idx += par->next_line * 8; 4700 + src_idx += par->next_line * 8; 4701 + } 4702 + } 4703 + } 4704 + 4705 + 4706 + static inline void expand_one_line(int bpp, unsigned long next_plane, 4707 + unsigned long *dst, int dst_idx, u32 n, 4708 + const u8 *data, u32 bgcolor, u32 fgcolor) 4709 + { 4710 + const unsigned long *src; 4711 + int src_idx; 4712 + 4713 + while (1) { 4714 + dst += dst_idx >> SHIFT_PER_LONG; 4715 + dst_idx &= (BITS_PER_LONG - 1); 4716 + if ((bgcolor ^ fgcolor) & 1) { 4717 + src = (unsigned long *) 4718 + ((unsigned long)data & ~(BYTES_PER_LONG - 1)); 4719 + src_idx = ((unsigned long)data & (BYTES_PER_LONG - 1)) * 8; 4720 + if (fgcolor & 1) 4721 + bitcpy(dst, dst_idx, src, src_idx, n); 4722 + else 4723 + bitcpy_not(dst, dst_idx, src, src_idx, n); 4724 + /* set or clear */ 4725 + } else 4726 + bitfill32(dst, dst_idx, fgcolor & 1 ? ~0 : 0, n); 4727 + if (!--bpp) 4728 + break; 4729 + bgcolor >>= 1; 4730 + fgcolor >>= 1; 4731 + dst_idx += next_plane * 8; 4732 + } 4733 + } 4734 + 4735 + 4736 + static void amifb_imageblit(struct fb_info *info, const struct fb_image *image) 4737 + { 4738 + struct amifb_par *par = info->par; 4739 + int x2, y2; 4740 + unsigned long *dst; 4741 + int dst_idx; 4742 + const char *src; 4743 + u32 dx, dy, width, height, pitch; 4744 + 4745 + /* 4746 + * We could use hardware clipping but on many cards you get around 4747 + * hardware clipping by writing to framebuffer directly like we are 4748 + * doing here. 4749 + */ 4750 + x2 = image->dx + image->width; 4751 + y2 = image->dy + image->height; 4752 + dx = image->dx; 4753 + dy = image->dy; 4754 + x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual; 4755 + y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual; 4756 + width = x2 - dx; 4757 + height = y2 - dy; 4758 + 4759 + if (image->depth == 1) { 4760 + dst = (unsigned long *) 4761 + ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1)); 4762 + dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8; 4763 + dst_idx += dy * par->next_line * 8 + dx; 4764 + src = image->data; 4765 + pitch = (image->width + 7) / 8; 4766 + while (height--) { 4767 + expand_one_line(info->var.bits_per_pixel, 4768 + par->next_plane, dst, dst_idx, width, 4769 + src, image->bg_color, 4770 + image->fg_color); 4771 + dst_idx += par->next_line * 8; 4772 + src += pitch; 4773 + } 4774 + } else { 4775 + c2p_planar(info->screen_base, image->data, dx, dy, width, 4776 + height, par->next_line, par->next_plane, 4777 + image->width, info->var.bits_per_pixel); 4778 + } 4779 + } 4780 + 4781 + 4782 + /* 4783 + * Amiga Frame Buffer Specific ioctls 4784 + */ 4785 + 4786 + static int amifb_ioctl(struct fb_info *info, 4787 + unsigned int cmd, unsigned long arg) 4788 + { 4789 + union { 4790 + struct fb_fix_cursorinfo fix; 4791 + struct fb_var_cursorinfo var; 4792 + struct fb_cursorstate state; 4793 + } crsr; 4794 + void __user *argp = (void __user *)arg; 4795 + int i; 4796 + 4797 + switch (cmd) { 4798 + case FBIOGET_FCURSORINFO: 4799 + i = ami_get_fix_cursorinfo(&crsr.fix, info->par); 4800 + if (i) 4801 + return i; 4802 + return copy_to_user(argp, &crsr.fix, 4803 + sizeof(crsr.fix)) ? -EFAULT : 0; 4804 + 4805 + case FBIOGET_VCURSORINFO: 4806 + i = ami_get_var_cursorinfo(&crsr.var, 4807 + ((struct fb_var_cursorinfo __user *)arg)->data, 4808 + info->par); 4809 + if (i) 4810 + return i; 4811 + return copy_to_user(argp, &crsr.var, 4812 + sizeof(crsr.var)) ? -EFAULT : 0; 4813 + 4814 + case FBIOPUT_VCURSORINFO: 4815 + if (copy_from_user(&crsr.var, argp, sizeof(crsr.var))) 4816 + return -EFAULT; 4817 + return ami_set_var_cursorinfo(&crsr.var, 4818 + ((struct fb_var_cursorinfo __user *)arg)->data, 4819 + info->par); 4820 + 4821 + case FBIOGET_CURSORSTATE: 4822 + i = ami_get_cursorstate(&crsr.state, info->par); 4823 + if (i) 4824 + return i; 4825 + return copy_to_user(argp, &crsr.state, 4826 + sizeof(crsr.state)) ? -EFAULT : 0; 4827 + 4828 + case FBIOPUT_CURSORSTATE: 4829 + if (copy_from_user(&crsr.state, argp, sizeof(crsr.state))) 4830 + return -EFAULT; 4831 + return ami_set_cursorstate(&crsr.state, info->par); 4832 + } 4833 + return -EINVAL; 4834 + } 4835 + 4836 + 4837 + /* 4838 + * Flash the cursor (called by VBlank interrupt) 4839 + */ 4840 + 4841 + static int flash_cursor(void) 4842 + { 4843 + static int cursorcount = 1; 4844 + 4845 + if (cursormode == FB_CURSOR_FLASH) { 4846 + if (!--cursorcount) { 4847 + cursorstate = -cursorstate; 4848 + cursorcount = cursorrate; 4849 + if (!is_blanked) 4850 + return 1; 4851 + } 4852 + } 4853 + return 0; 2308 4854 } 2309 4855 2310 4856 /* 2311 - * Rebuild the Copper List 2312 - * 2313 - * We only change the things that are not static 4857 + * VBlank Display Interrupt 2314 4858 */ 2315 4859 2316 - static void ami_rebuild_copper(void) 4860 + static irqreturn_t amifb_interrupt(int irq, void *dev_id) 2317 4861 { 2318 - struct amifb_par *par = &currentpar; 2319 - copins *copl, *cops; 2320 - u_short line, h_end1, h_end2; 2321 - short i; 2322 - u_long p; 4862 + struct amifb_par *par = dev_id; 2323 4863 2324 - if (IS_AGA && maxfmode + par->clk_shift == 0) 2325 - h_end1 = par->diwstrt_h-64; 2326 - else 2327 - h_end1 = par->htotal-32; 2328 - h_end2 = par->ddfstop+64; 4864 + if (do_vmode_pan || do_vmode_full) 4865 + ami_update_display(par); 2329 4866 2330 - ami_set_sprite(); 4867 + if (do_vmode_full) 4868 + ami_init_display(par); 2331 4869 2332 - copl = copdisplay.rebuild[1]; 2333 - p = par->bplpt0; 2334 - if (par->vmode & FB_VMODE_YWRAP) { 2335 - if ((par->vyres-par->yoffset) != 1 || !mod2(par->diwstrt_v)) { 2336 - if (par->yoffset > par->vyres-par->yres) { 2337 - for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) { 2338 - (copl++)->l = CMOVE(highw(p), bplpt[i]); 2339 - (copl++)->l = CMOVE2(loww(p), bplpt[i]); 2340 - } 2341 - line = par->diwstrt_v + ((par->vyres-par->yoffset)<<par->line_shift) - 1; 2342 - while (line >= 512) { 2343 - (copl++)->l = CWAIT(h_end1, 510); 2344 - line -= 512; 2345 - } 2346 - if (line >= 510 && IS_AGA && maxfmode + par->clk_shift == 0) 2347 - (copl++)->l = CWAIT(h_end1, line); 2348 - else 2349 - (copl++)->l = CWAIT(h_end2, line); 2350 - p = par->bplpt0wrap; 2351 - } 2352 - } else p = par->bplpt0wrap; 4870 + if (do_vmode_pan) { 4871 + flash_cursor(); 4872 + ami_rebuild_copper(par); 4873 + do_cursor = do_vmode_pan = 0; 4874 + } else if (do_cursor) { 4875 + flash_cursor(); 4876 + ami_set_sprite(par); 4877 + do_cursor = 0; 4878 + } else { 4879 + if (flash_cursor()) 4880 + ami_set_sprite(par); 2353 4881 } 2354 - for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) { 2355 - (copl++)->l = CMOVE(highw(p), bplpt[i]); 2356 - (copl++)->l = CMOVE2(loww(p), bplpt[i]); 2357 - } 2358 - copl->l = CEND; 2359 4882 2360 - if (par->bplcon0 & BPC0_LACE) { 2361 - cops = copdisplay.rebuild[0]; 2362 - p = par->bplpt0; 2363 - if (mod2(par->diwstrt_v)) 2364 - p -= par->next_line; 2365 - else 2366 - p += par->next_line; 2367 - if (par->vmode & FB_VMODE_YWRAP) { 2368 - if ((par->vyres-par->yoffset) != 1 || mod2(par->diwstrt_v)) { 2369 - if (par->yoffset > par->vyres-par->yres+1) { 2370 - for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) { 2371 - (cops++)->l = CMOVE(highw(p), bplpt[i]); 2372 - (cops++)->l = CMOVE2(loww(p), bplpt[i]); 2373 - } 2374 - line = par->diwstrt_v + ((par->vyres-par->yoffset)<<par->line_shift) - 2; 2375 - while (line >= 512) { 2376 - (cops++)->l = CWAIT(h_end1, 510); 2377 - line -= 512; 2378 - } 2379 - if (line > 510 && IS_AGA && maxfmode + par->clk_shift == 0) 2380 - (cops++)->l = CWAIT(h_end1, line); 2381 - else 2382 - (cops++)->l = CWAIT(h_end2, line); 2383 - p = par->bplpt0wrap; 2384 - if (mod2(par->diwstrt_v+par->vyres-par->yoffset)) 2385 - p -= par->next_line; 2386 - else 2387 - p += par->next_line; 2388 - } 2389 - } else p = par->bplpt0wrap - par->next_line; 2390 - } 2391 - for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) { 2392 - (cops++)->l = CMOVE(highw(p), bplpt[i]); 2393 - (cops++)->l = CMOVE2(loww(p), bplpt[i]); 2394 - } 2395 - cops->l = CEND; 4883 + if (do_blank) { 4884 + ami_do_blank(par); 4885 + do_blank = 0; 2396 4886 } 4887 + 4888 + if (do_vmode_full) { 4889 + ami_reinit_copper(par); 4890 + do_vmode_full = 0; 4891 + } 4892 + return IRQ_HANDLED; 2397 4893 } 4894 + 4895 + 4896 + static struct fb_ops amifb_ops = { 4897 + .owner = THIS_MODULE, 4898 + .fb_check_var = amifb_check_var, 4899 + .fb_set_par = amifb_set_par, 4900 + .fb_setcolreg = amifb_setcolreg, 4901 + .fb_blank = amifb_blank, 4902 + .fb_pan_display = amifb_pan_display, 4903 + .fb_fillrect = amifb_fillrect, 4904 + .fb_copyarea = amifb_copyarea, 4905 + .fb_imageblit = amifb_imageblit, 4906 + .fb_ioctl = amifb_ioctl, 4907 + }; 4908 + 4909 + 4910 + /* 4911 + * Allocate, Clear and Align a Block of Chip Memory 4912 + */ 4913 + 4914 + static void *aligned_chipptr; 4915 + 4916 + static inline u_long __init chipalloc(u_long size) 4917 + { 4918 + aligned_chipptr = amiga_chip_alloc(size, "amifb [RAM]"); 4919 + if (!aligned_chipptr) { 4920 + pr_err("amifb: No Chip RAM for frame buffer"); 4921 + return 0; 4922 + } 4923 + memset(aligned_chipptr, 0, size); 4924 + return (u_long)aligned_chipptr; 4925 + } 4926 + 4927 + static inline void chipfree(void) 4928 + { 4929 + if (aligned_chipptr) 4930 + amiga_chip_free(aligned_chipptr); 4931 + } 4932 + 4933 + 4934 + /* 4935 + * Initialisation 4936 + */ 4937 + 4938 + static int __init amifb_probe(struct platform_device *pdev) 4939 + { 4940 + struct fb_info *info; 4941 + int tag, i, err = 0; 4942 + u_long chipptr; 4943 + u_int defmode; 4944 + 4945 + #ifndef MODULE 4946 + char *option = NULL; 4947 + 4948 + if (fb_get_options("amifb", &option)) { 4949 + amifb_video_off(); 4950 + return -ENODEV; 4951 + } 4952 + amifb_setup(option); 4953 + #endif 4954 + custom.dmacon = DMAF_ALL | DMAF_MASTER; 4955 + 4956 + info = framebuffer_alloc(sizeof(struct amifb_par), &pdev->dev); 4957 + if (!info) { 4958 + dev_err(&pdev->dev, "framebuffer_alloc failed\n"); 4959 + return -ENOMEM; 4960 + } 4961 + 4962 + strcpy(info->fix.id, "Amiga "); 4963 + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; 4964 + info->fix.accel = FB_ACCEL_AMIGABLITT; 4965 + 4966 + switch (amiga_chipset) { 4967 + #ifdef CONFIG_FB_AMIGA_OCS 4968 + case CS_OCS: 4969 + strcat(info->fix.id, "OCS"); 4970 + default_chipset: 4971 + chipset = TAG_OCS; 4972 + maxdepth[TAG_SHRES] = 0; /* OCS means no SHRES */ 4973 + maxdepth[TAG_HIRES] = 4; 4974 + maxdepth[TAG_LORES] = 6; 4975 + maxfmode = TAG_FMODE_1; 4976 + defmode = amiga_vblank == 50 ? DEFMODE_PAL : DEFMODE_NTSC; 4977 + info->fix.smem_len = VIDEOMEMSIZE_OCS; 4978 + break; 4979 + #endif /* CONFIG_FB_AMIGA_OCS */ 4980 + 4981 + #ifdef CONFIG_FB_AMIGA_ECS 4982 + case CS_ECS: 4983 + strcat(info->fix.id, "ECS"); 4984 + chipset = TAG_ECS; 4985 + maxdepth[TAG_SHRES] = 2; 4986 + maxdepth[TAG_HIRES] = 4; 4987 + maxdepth[TAG_LORES] = 6; 4988 + maxfmode = TAG_FMODE_1; 4989 + if (AMIGAHW_PRESENT(AMBER_FF)) 4990 + defmode = amiga_vblank == 50 ? DEFMODE_AMBER_PAL 4991 + : DEFMODE_AMBER_NTSC; 4992 + else 4993 + defmode = amiga_vblank == 50 ? DEFMODE_PAL 4994 + : DEFMODE_NTSC; 4995 + if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT > 4996 + VIDEOMEMSIZE_ECS_2M) 4997 + info->fix.smem_len = VIDEOMEMSIZE_ECS_2M; 4998 + else 4999 + info->fix.smem_len = VIDEOMEMSIZE_ECS_1M; 5000 + break; 5001 + #endif /* CONFIG_FB_AMIGA_ECS */ 5002 + 5003 + #ifdef CONFIG_FB_AMIGA_AGA 5004 + case CS_AGA: 5005 + strcat(info->fix.id, "AGA"); 5006 + chipset = TAG_AGA; 5007 + maxdepth[TAG_SHRES] = 8; 5008 + maxdepth[TAG_HIRES] = 8; 5009 + maxdepth[TAG_LORES] = 8; 5010 + maxfmode = TAG_FMODE_4; 5011 + defmode = DEFMODE_AGA; 5012 + if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT > 5013 + VIDEOMEMSIZE_AGA_2M) 5014 + info->fix.smem_len = VIDEOMEMSIZE_AGA_2M; 5015 + else 5016 + info->fix.smem_len = VIDEOMEMSIZE_AGA_1M; 5017 + break; 5018 + #endif /* CONFIG_FB_AMIGA_AGA */ 5019 + 5020 + default: 5021 + #ifdef CONFIG_FB_AMIGA_OCS 5022 + printk("Unknown graphics chipset, defaulting to OCS\n"); 5023 + strcat(info->fix.id, "Unknown"); 5024 + goto default_chipset; 5025 + #else /* CONFIG_FB_AMIGA_OCS */ 5026 + err = -ENODEV; 5027 + goto release; 5028 + #endif /* CONFIG_FB_AMIGA_OCS */ 5029 + break; 5030 + } 5031 + 5032 + /* 5033 + * Calculate the Pixel Clock Values for this Machine 5034 + */ 5035 + 5036 + { 5037 + u_long tmp = DIVUL(200000000000ULL, amiga_eclock); 5038 + 5039 + pixclock[TAG_SHRES] = (tmp + 4) / 8; /* SHRES: 35 ns / 28 MHz */ 5040 + pixclock[TAG_HIRES] = (tmp + 2) / 4; /* HIRES: 70 ns / 14 MHz */ 5041 + pixclock[TAG_LORES] = (tmp + 1) / 2; /* LORES: 140 ns / 7 MHz */ 5042 + } 5043 + 5044 + /* 5045 + * Replace the Tag Values with the Real Pixel Clock Values 5046 + */ 5047 + 5048 + for (i = 0; i < NUM_TOTAL_MODES; i++) { 5049 + struct fb_videomode *mode = &ami_modedb[i]; 5050 + tag = mode->pixclock; 5051 + if (tag == TAG_SHRES || tag == TAG_HIRES || tag == TAG_LORES) { 5052 + mode->pixclock = pixclock[tag]; 5053 + } 5054 + } 5055 + 5056 + if (amifb_hfmin) { 5057 + info->monspecs.hfmin = amifb_hfmin; 5058 + info->monspecs.hfmax = amifb_hfmax; 5059 + info->monspecs.vfmin = amifb_vfmin; 5060 + info->monspecs.vfmax = amifb_vfmax; 5061 + } else { 5062 + /* 5063 + * These are for a typical Amiga monitor (e.g. A1960) 5064 + */ 5065 + info->monspecs.hfmin = 15000; 5066 + info->monspecs.hfmax = 38000; 5067 + info->monspecs.vfmin = 49; 5068 + info->monspecs.vfmax = 90; 5069 + } 5070 + 5071 + info->fbops = &amifb_ops; 5072 + info->flags = FBINFO_DEFAULT; 5073 + info->device = &pdev->dev; 5074 + 5075 + if (!fb_find_mode(&info->var, info, mode_option, ami_modedb, 5076 + NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) { 5077 + err = -EINVAL; 5078 + goto release; 5079 + } 5080 + 5081 + fb_videomode_to_modelist(ami_modedb, NUM_TOTAL_MODES, 5082 + &info->modelist); 5083 + 5084 + round_down_bpp = 0; 5085 + chipptr = chipalloc(info->fix.smem_len + SPRITEMEMSIZE + 5086 + DUMMYSPRITEMEMSIZE + COPINITSIZE + 5087 + 4 * COPLISTSIZE); 5088 + if (!chipptr) { 5089 + err = -ENOMEM; 5090 + goto release; 5091 + } 5092 + 5093 + assignchunk(videomemory, u_long, chipptr, info->fix.smem_len); 5094 + assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE); 5095 + assignchunk(dummysprite, u_short *, chipptr, DUMMYSPRITEMEMSIZE); 5096 + assignchunk(copdisplay.init, copins *, chipptr, COPINITSIZE); 5097 + assignchunk(copdisplay.list[0][0], copins *, chipptr, COPLISTSIZE); 5098 + assignchunk(copdisplay.list[0][1], copins *, chipptr, COPLISTSIZE); 5099 + assignchunk(copdisplay.list[1][0], copins *, chipptr, COPLISTSIZE); 5100 + assignchunk(copdisplay.list[1][1], copins *, chipptr, COPLISTSIZE); 5101 + 5102 + /* 5103 + * access the videomem with writethrough cache 5104 + */ 5105 + info->fix.smem_start = (u_long)ZTWO_PADDR(videomemory); 5106 + videomemory = (u_long)ioremap_writethrough(info->fix.smem_start, 5107 + info->fix.smem_len); 5108 + if (!videomemory) { 5109 + dev_warn(&pdev->dev, 5110 + "Unable to map videomem cached writethrough\n"); 5111 + info->screen_base = (char *)ZTWO_VADDR(info->fix.smem_start); 5112 + } else 5113 + info->screen_base = (char *)videomemory; 5114 + 5115 + memset(dummysprite, 0, DUMMYSPRITEMEMSIZE); 5116 + 5117 + /* 5118 + * Make sure the Copper has something to do 5119 + */ 5120 + ami_init_copper(); 5121 + 5122 + /* 5123 + * Enable Display DMA 5124 + */ 5125 + custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER | 5126 + DMAF_BLITTER | DMAF_SPRITE; 5127 + 5128 + err = request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, 0, 5129 + "fb vertb handler", info->par); 5130 + if (err) 5131 + goto disable_dma; 5132 + 5133 + err = fb_alloc_cmap(&info->cmap, 1 << info->var.bits_per_pixel, 0); 5134 + if (err) 5135 + goto free_irq; 5136 + 5137 + dev_set_drvdata(&pdev->dev, info); 5138 + 5139 + err = register_framebuffer(info); 5140 + if (err) 5141 + goto unset_drvdata; 5142 + 5143 + printk("fb%d: %s frame buffer device, using %dK of video memory\n", 5144 + info->node, info->fix.id, info->fix.smem_len>>10); 5145 + 5146 + return 0; 5147 + 5148 + unset_drvdata: 5149 + dev_set_drvdata(&pdev->dev, NULL); 5150 + fb_dealloc_cmap(&info->cmap); 5151 + free_irq: 5152 + free_irq(IRQ_AMIGA_COPPER, info->par); 5153 + disable_dma: 5154 + custom.dmacon = DMAF_ALL | DMAF_MASTER; 5155 + if (videomemory) 5156 + iounmap((void *)videomemory); 5157 + chipfree(); 5158 + release: 5159 + framebuffer_release(info); 5160 + return err; 5161 + } 5162 + 2398 5163 2399 5164 static int __exit amifb_remove(struct platform_device *pdev) 2400 5165 { 2401 - unregister_framebuffer(&fb_info); 2402 - amifb_deinit(pdev); 5166 + struct fb_info *info = dev_get_drvdata(&pdev->dev); 5167 + 5168 + unregister_framebuffer(info); 5169 + dev_set_drvdata(&pdev->dev, NULL); 5170 + fb_dealloc_cmap(&info->cmap); 5171 + free_irq(IRQ_AMIGA_COPPER, info->par); 5172 + custom.dmacon = DMAF_ALL | DMAF_MASTER; 5173 + if (videomemory) 5174 + iounmap((void *)videomemory); 5175 + chipfree(); 5176 + framebuffer_release(info); 2403 5177 amifb_video_off(); 2404 5178 return 0; 2405 5179 }
+27 -8
drivers/video/atmel_lcdfb.c
··· 100 100 brightness = 0; 101 101 102 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 105 brightness ? contrast_ctr : 0); 106 + else 107 + lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr); 105 108 106 109 bl->props.fb_blank = bl->props.power = sinfo->bl_power = power; 107 110 ··· 685 682 686 683 case FB_VISUAL_PSEUDOCOLOR: 687 684 if (regno < 256) { 688 - val = ((red >> 11) & 0x001f); 689 - val |= ((green >> 6) & 0x03e0); 690 - val |= ((blue >> 1) & 0x7c00); 685 + if (cpu_is_at91sam9261() || cpu_is_at91sam9263() 686 + || cpu_is_at91sam9rl()) { 687 + /* old style I+BGR:555 */ 688 + val = ((red >> 11) & 0x001f); 689 + val |= ((green >> 6) & 0x03e0); 690 + val |= ((blue >> 1) & 0x7c00); 691 691 692 - /* 693 - * TODO: intensity bit. Maybe something like 694 - * ~(red[10] ^ green[10] ^ blue[10]) & 1 695 - */ 692 + /* 693 + * TODO: intensity bit. Maybe something like 694 + * ~(red[10] ^ green[10] ^ blue[10]) & 1 695 + */ 696 + } else { 697 + /* new style BGR:565 / RGB:565 */ 698 + if (sinfo->lcd_wiring_mode == 699 + ATMEL_LCDC_WIRING_RGB) { 700 + val = ((blue >> 11) & 0x001f); 701 + val |= ((red >> 0) & 0xf800); 702 + } else { 703 + val = ((red >> 11) & 0x001f); 704 + val |= ((blue >> 0) & 0xf800); 705 + } 706 + 707 + val |= ((green >> 5) & 0x07e0); 708 + } 696 709 697 710 lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val); 698 711 ret = 0;
+145 -125
drivers/video/cirrusfb.c
··· 280 280 #endif /* CONFIG_PCI */ 281 281 282 282 #ifdef CONFIG_ZORRO 283 - static const struct zorro_device_id cirrusfb_zorro_table[] = { 283 + struct 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 + 293 + static const struct zorrocl zcl_sd64 __devinitconst = { 294 + .type = BT_SD64, 295 + .ramid = ZORRO_PROD_HELFRICH_SD64_RAM, 296 + }; 297 + 298 + static const struct zorrocl zcl_piccolo __devinitconst = { 299 + .type = BT_PICCOLO, 300 + .ramid = ZORRO_PROD_HELFRICH_PICCOLO_RAM, 301 + }; 302 + 303 + static const struct zorrocl zcl_picasso __devinitconst = { 304 + .type = BT_PICASSO, 305 + .ramid = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM, 306 + }; 307 + 308 + static const struct zorrocl zcl_spectrum __devinitconst = { 309 + .type = BT_SPECTRUM, 310 + .ramid = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM, 311 + }; 312 + 313 + static 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 + 320 + static 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 + 328 + static const struct zorro_device_id cirrusfb_zorro_table[] __devinitconst = { 284 329 { 285 - .id = ZORRO_PROD_HELFRICH_SD64_RAM, 286 - .driver_data = BT_SD64, 330 + .id = ZORRO_PROD_HELFRICH_SD64_REG, 331 + .driver_data = (unsigned long)&zcl_sd64, 287 332 }, { 288 - .id = ZORRO_PROD_HELFRICH_PICCOLO_RAM, 289 - .driver_data = BT_PICCOLO, 333 + .id = ZORRO_PROD_HELFRICH_PICCOLO_REG, 334 + .driver_data = (unsigned long)&zcl_piccolo, 290 335 }, { 291 - .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM, 292 - .driver_data = BT_PICASSO, 336 + .id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG, 337 + .driver_data = (unsigned long)&zcl_picasso, 293 338 }, { 294 - .id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM, 295 - .driver_data = BT_SPECTRUM, 339 + .id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG, 340 + .driver_data = (unsigned long)&zcl_spectrum, 296 341 }, { 297 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 348 { 0 } 301 349 }; 302 350 MODULE_DEVICE_TABLE(zorro, cirrusfb_zorro_table); 303 - 304 - static 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 351 #endif /* CONFIG_ZORRO */ 330 352 331 353 #ifdef CIRRUSFB_DEBUG ··· 1978 1956 struct cirrusfb_info *cinfo = info->par; 1979 1957 struct zorro_dev *zdev = to_zorro_dev(info->device); 1980 1958 1981 - zorro_release_device(zdev); 1982 - 1983 - if (cinfo->btype == BT_PICASSO4) { 1984 - cinfo->regbase -= 0x600000; 1985 - iounmap((void *)cinfo->regbase); 1959 + if (info->fix.smem_start > 16 * MB_) 1986 1960 iounmap(info->screen_base); 1987 - } else { 1988 - if (zorro_resource_start(zdev) > 0x01000000) 1989 - iounmap(info->screen_base); 1990 - } 1961 + if (info->fix.mmio_start > 16 * MB_) 1962 + iounmap(cinfo->regbase); 1963 + 1964 + zorro_release_device(zdev); 1991 1965 } 1992 1966 #endif /* CONFIG_ZORRO */ 1993 1967 ··· 2240 2222 static int __devinit cirrusfb_zorro_register(struct zorro_dev *z, 2241 2223 const struct zorro_device_id *ent) 2242 2224 { 2243 - struct cirrusfb_info *cinfo; 2244 2225 struct fb_info *info; 2226 + int error; 2227 + const struct zorrocl *zcl; 2245 2228 enum cirrus_board btype; 2246 - struct zorro_dev *z2 = NULL; 2247 - unsigned long board_addr, board_size, size; 2248 - int ret; 2249 - 2250 - btype = ent->driver_data; 2251 - if (cirrusfb_zorro_table2[btype].id2) 2252 - z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL); 2253 - size = cirrusfb_zorro_table2[btype].size; 2229 + unsigned long regbase, ramsize, rambase; 2230 + struct cirrusfb_info *cinfo; 2254 2231 2255 2232 info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev); 2256 2233 if (!info) { 2257 2234 printk(KERN_ERR "cirrusfb: could not allocate memory\n"); 2258 - ret = -ENOMEM; 2259 - goto err_out; 2235 + return -ENOMEM; 2260 2236 } 2261 2237 2262 - dev_info(info->device, "%s board detected\n", 2263 - cirrusfb_board_info[btype].name); 2238 + zcl = (const struct zorrocl *)ent->driver_data; 2239 + btype = zcl->type; 2240 + regbase = zorro_resource_start(z) + zcl->regoffset; 2241 + ramsize = zcl->ramsize; 2242 + if (ramsize) { 2243 + rambase = zorro_resource_start(z) + zcl->ramoffset; 2244 + if (zorro_resource_len(z) == 64 * MB_) { 2245 + /* Quirk for 64 MiB Picasso IV */ 2246 + rambase += zcl->ramoffset; 2247 + } 2248 + } else { 2249 + struct zorro_dev *ram = zorro_find_device(zcl->ramid, NULL); 2250 + if (!ram || !zorro_resource_len(ram)) { 2251 + dev_err(info->device, "No video RAM found\n"); 2252 + error = -ENODEV; 2253 + goto err_release_fb; 2254 + } 2255 + rambase = zorro_resource_start(ram); 2256 + ramsize = zorro_resource_len(ram); 2257 + if (zcl->ramid2 && 2258 + (ram = zorro_find_device(zcl->ramid2, NULL))) { 2259 + if (zorro_resource_start(ram) != rambase + ramsize) { 2260 + dev_warn(info->device, 2261 + "Skipping non-contiguous RAM at %pR\n", 2262 + &ram->resource); 2263 + } else { 2264 + ramsize += zorro_resource_len(ram); 2265 + } 2266 + } 2267 + } 2268 + 2269 + dev_info(info->device, 2270 + "%s board detected, REG at 0x%lx, %lu MiB RAM at 0x%lx\n", 2271 + cirrusfb_board_info[btype].name, regbase, ramsize / MB_, 2272 + rambase); 2273 + 2274 + if (!zorro_request_device(z, "cirrusfb")) { 2275 + dev_err(info->device, "Cannot reserve %pR\n", &z->resource); 2276 + error = -EBUSY; 2277 + goto err_release_fb; 2278 + } 2264 2279 2265 2280 cinfo = info->par; 2266 2281 cinfo->btype = btype; 2267 2282 2268 - assert(z); 2269 - assert(btype != BT_NONE); 2270 - 2271 - board_addr = zorro_resource_start(z); 2272 - board_size = zorro_resource_len(z); 2273 - info->screen_size = size; 2274 - 2275 - if (!zorro_request_device(z, "cirrusfb")) { 2276 - dev_err(info->device, "cannot reserve region 0x%lx, abort\n", 2277 - board_addr); 2278 - ret = -EBUSY; 2279 - goto err_release_fb; 2283 + info->fix.mmio_start = regbase; 2284 + cinfo->regbase = regbase > 16 * MB_ ? ioremap(regbase, 64 * 1024) 2285 + : (caddr_t)ZTWO_VADDR(regbase); 2286 + if (!cinfo->regbase) { 2287 + dev_err(info->device, "Cannot map registers\n"); 2288 + error = -EIO; 2289 + goto err_release_dev; 2280 2290 } 2281 2291 2282 - ret = -EIO; 2283 - 2284 - if (btype == BT_PICASSO4) { 2285 - dev_info(info->device, " REG at $%lx\n", board_addr + 0x600000); 2286 - 2287 - /* To be precise, for the P4 this is not the */ 2288 - /* begin of the board, but the begin of RAM. */ 2289 - /* for P4, map in its address space in 2 chunks (### TEST! ) */ 2290 - /* (note the ugly hardcoded 16M number) */ 2291 - cinfo->regbase = ioremap(board_addr, 16777216); 2292 - if (!cinfo->regbase) 2293 - goto err_release_region; 2294 - 2295 - dev_dbg(info->device, "Virtual address for board set to: $%p\n", 2296 - cinfo->regbase); 2297 - cinfo->regbase += 0x600000; 2298 - info->fix.mmio_start = board_addr + 0x600000; 2299 - 2300 - info->fix.smem_start = board_addr + 16777216; 2301 - info->screen_base = ioremap(info->fix.smem_start, 16777216); 2302 - if (!info->screen_base) 2303 - goto err_unmap_regbase; 2304 - } else { 2305 - dev_info(info->device, " REG at $%lx\n", 2306 - (unsigned long) z2->resource.start); 2307 - 2308 - info->fix.smem_start = board_addr; 2309 - if (board_addr > 0x01000000) 2310 - info->screen_base = ioremap(board_addr, board_size); 2311 - else 2312 - info->screen_base = (caddr_t) ZTWO_VADDR(board_addr); 2313 - if (!info->screen_base) 2314 - goto err_release_region; 2315 - 2316 - /* set address for REG area of board */ 2317 - cinfo->regbase = (caddr_t) ZTWO_VADDR(z2->resource.start); 2318 - info->fix.mmio_start = z2->resource.start; 2319 - 2320 - dev_dbg(info->device, "Virtual address for board set to: $%p\n", 2321 - cinfo->regbase); 2292 + info->fix.smem_start = rambase; 2293 + info->screen_size = ramsize; 2294 + info->screen_base = rambase > 16 * MB_ ? ioremap(rambase, ramsize) 2295 + : (caddr_t)ZTWO_VADDR(rambase); 2296 + if (!info->screen_base) { 2297 + dev_err(info->device, "Cannot map video RAM\n"); 2298 + error = -EIO; 2299 + goto err_unmap_reg; 2322 2300 } 2301 + 2323 2302 cinfo->unmap = cirrusfb_zorro_unmap; 2324 2303 2325 2304 dev_info(info->device, 2326 - "Cirrus Logic chipset on Zorro bus, RAM (%lu MB) at $%lx\n", 2327 - board_size / MB_, board_addr); 2328 - 2329 - zorro_set_drvdata(z, info); 2305 + "Cirrus Logic chipset on Zorro bus, RAM (%lu MiB) at 0x%lx\n", 2306 + ramsize / MB_, rambase); 2330 2307 2331 2308 /* MCLK select etc. */ 2332 2309 if (cirrusfb_board_info[btype].init_sr1f) 2333 2310 vga_wseq(cinfo->regbase, CL_SEQR1F, 2334 2311 cirrusfb_board_info[btype].sr1f); 2335 2312 2336 - ret = cirrusfb_register(info); 2337 - if (!ret) 2338 - return 0; 2313 + error = cirrusfb_register(info); 2314 + if (error) { 2315 + dev_err(info->device, "Failed to register device, error %d\n", 2316 + error); 2317 + goto err_unmap_ram; 2318 + } 2339 2319 2340 - if (btype == BT_PICASSO4 || board_addr > 0x01000000) 2320 + zorro_set_drvdata(z, info); 2321 + return 0; 2322 + 2323 + err_unmap_ram: 2324 + if (rambase > 16 * MB_) 2341 2325 iounmap(info->screen_base); 2342 2326 2343 - err_unmap_regbase: 2344 - if (btype == BT_PICASSO4) 2345 - iounmap(cinfo->regbase - 0x600000); 2346 - err_release_region: 2347 - release_region(board_addr, board_size); 2327 + err_unmap_reg: 2328 + if (regbase > 16 * MB_) 2329 + iounmap(cinfo->regbase); 2330 + err_release_dev: 2331 + zorro_release_device(z); 2348 2332 err_release_fb: 2349 2333 framebuffer_release(info); 2350 - err_out: 2351 - return ret; 2334 + return error; 2352 2335 } 2353 2336 2354 2337 void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z) ··· 2357 2338 struct fb_info *info = zorro_get_drvdata(z); 2358 2339 2359 2340 cirrusfb_cleanup(info); 2341 + zorro_set_drvdata(z, NULL); 2360 2342 } 2361 2343 2362 2344 static struct zorro_driver cirrusfb_zorro_driver = {
+1 -1
drivers/video/controlfb.c
··· 420 420 421 421 /* Try to pick a video mode out of NVRAM if we have one. */ 422 422 #ifdef CONFIG_NVRAM 423 - if (default_cmode == CMODE_NVRAM){ 423 + if (default_cmode == CMODE_NVRAM) { 424 424 cmode = nvram_read_byte(NV_CMODE); 425 425 if(cmode < CMODE_8 || cmode > CMODE_32) 426 426 cmode = CMODE_8;
-24
drivers/video/display/Kconfig
··· 1 - # 2 - # Display drivers configuration 3 - # 4 - 5 - menu "Display device support" 6 - 7 - config 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 - 21 - comment "Display hardware drivers" 22 - depends on DISPLAY_SUPPORT 23 - 24 - endmenu
-6
drivers/video/display/Makefile
··· 1 - # Display drivers 2 - 3 - display-objs := display-sysfs.o 4 - 5 - obj-$(CONFIG_DISPLAY_SUPPORT) += display.o 6 -
-219
drivers/video/display/display-sysfs.c
··· 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 - 32 - static 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 - 39 - static 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 - 46 - static 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 - 59 - static 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 - 87 - static 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 - 101 - static 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 - 108 - static 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 - 119 - static 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 - 130 - static struct mutex allocated_dsp_lock; 131 - static DEFINE_IDR(allocated_dsp); 132 - static struct class *display_class; 133 - 134 - struct 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 - } 175 - EXPORT_SYMBOL(display_device_register); 176 - 177 - void 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 - } 191 - EXPORT_SYMBOL(display_device_unregister); 192 - 193 - static 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 - 208 - static void __exit display_class_exit(void) 209 - { 210 - class_destroy(display_class); 211 - } 212 - 213 - module_init(display_class_init); 214 - module_exit(display_class_exit); 215 - 216 - MODULE_DESCRIPTION("Display Hardware handling"); 217 - MODULE_AUTHOR("James Simmons <jsimmons@infradead.org>"); 218 - MODULE_LICENSE("GPL"); 219 -
+14
drivers/video/fbmem.c
··· 967 967 memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) { 968 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 984 if (!info->fbops->fb_check_var) { 971 985 *var = info->var; 972 986 goto done;
+271 -306
drivers/video/fsl-diu-fb.c
··· 36 36 #include <linux/fsl-diu-fb.h> 37 37 #include "edid.h" 38 38 39 - #define FSL_AOI_NUM 6 /* 5 AOIs and one dummy AOI */ 40 - /* 1 for plane 0, 2 for plane 1&2 each */ 39 + #define NUM_AOIS 5 /* 1 for plane 0, 2 for planes 1 & 2 each */ 41 40 42 41 /* HW cursor parameters */ 43 42 #define MAX_CURS 32 ··· 47 48 #define INT_UNDRUN 0x04 /* Under run exception interrupt */ 48 49 #define INT_PARERR 0x08 /* Display parameters error interrupt */ 49 50 #define INT_LS_BF_VS 0x10 /* Lines before vsync. interrupt */ 50 - 51 - struct diu_addr { 52 - void *vaddr; /* Virtual address */ 53 - dma_addr_t paddr; /* Physical address */ 54 - __u32 offset; 55 - }; 56 51 57 52 /* 58 53 * List of supported video modes ··· 323 330 324 331 static DEFINE_SPINLOCK(diu_lock); 325 332 326 - struct fsl_diu_data { 327 - struct fb_info *fsl_diu_info[FSL_AOI_NUM - 1]; 328 - /*FSL_AOI_NUM has one dummy AOI */ 329 - struct device_attribute dev_attr; 330 - struct diu_ad *dummy_ad; 331 - void *dummy_aoi_virt; 332 - unsigned int irq; 333 - int fb_enabled; 334 - enum fsl_diu_monitor_port monitor_port; 335 - struct diu __iomem *diu_reg; 336 - spinlock_t reg_lock; 337 - struct diu_addr ad; 338 - struct diu_addr gamma; 339 - struct diu_addr pallete; 340 - struct diu_addr cursor; 341 - }; 342 - 343 333 enum mfb_index { 344 334 PLANE0 = 0, /* Plane 0, only one AOI that fills the screen */ 345 335 PLANE1_AOI0, /* Plane 1, first AOI */ ··· 346 370 u8 *edid_data; 347 371 }; 348 372 373 + /** 374 + * struct fsl_diu_data - per-DIU data structure 375 + * @dma_addr: DMA address of this structure 376 + * @fsl_diu_info: fb_info objects, one per AOI 377 + * @dev_attr: sysfs structure 378 + * @irq: IRQ 379 + * @monitor_port: the monitor port this DIU is connected to 380 + * @diu_reg: pointer to the DIU hardware registers 381 + * @reg_lock: spinlock for register access 382 + * @dummy_aoi: video buffer for the 4x4 32-bit dummy AOI 383 + * dummy_ad: DIU Area Descriptor for the dummy AOI 384 + * @ad[]: Area Descriptors for each real AOI 385 + * @gamma: gamma color table 386 + * @cursor: hardware cursor data 387 + * 388 + * This data structure must be allocated with 32-byte alignment, so that the 389 + * internal fields can be aligned properly. 390 + */ 391 + struct fsl_diu_data { 392 + dma_addr_t dma_addr; 393 + struct fb_info fsl_diu_info[NUM_AOIS]; 394 + struct mfb_info mfb[NUM_AOIS]; 395 + struct device_attribute dev_attr; 396 + unsigned int irq; 397 + enum fsl_diu_monitor_port monitor_port; 398 + struct diu __iomem *diu_reg; 399 + spinlock_t reg_lock; 400 + u8 dummy_aoi[4 * 4 * 4]; 401 + struct diu_ad dummy_ad __aligned(8); 402 + struct diu_ad ad[NUM_AOIS] __aligned(8); 403 + u8 gamma[256 * 3] __aligned(32); 404 + u8 cursor[MAX_CURS * MAX_CURS * 2] __aligned(32); 405 + } __aligned(32); 406 + 407 + /* Determine the DMA address of a member of the fsl_diu_data structure */ 408 + #define DMA_ADDR(p, f) ((p)->dma_addr + offsetof(struct fsl_diu_data, f)) 349 409 350 410 static struct mfb_info mfb_template[] = { 351 411 { ··· 461 449 return diu_ops.valid_monitor_port(port); 462 450 } 463 451 464 - /** 465 - * fsl_diu_alloc - allocate memory for the DIU 466 - * @size: number of bytes to allocate 467 - * @param: returned physical address of memory 468 - * 469 - * This function allocates a physically-contiguous block of memory. 470 - */ 471 - static void *fsl_diu_alloc(size_t size, phys_addr_t *phys) 472 - { 473 - void *virt; 474 - 475 - virt = alloc_pages_exact(size, GFP_DMA | __GFP_ZERO); 476 - if (virt) 477 - *phys = virt_to_phys(virt); 478 - 479 - return virt; 480 - } 481 - 482 - /** 483 - * fsl_diu_free - release DIU memory 484 - * @virt: pointer returned by fsl_diu_alloc() 485 - * @size: number of bytes allocated by fsl_diu_alloc() 486 - * 487 - * This function releases memory allocated by fsl_diu_alloc(). 488 - */ 489 - static void fsl_diu_free(void *virt, size_t size) 490 - { 491 - if (virt && size) 492 - free_pages_exact(virt, size); 493 - } 494 - 495 452 /* 496 453 * Workaround for failed writing desc register of planes. 497 454 * Needed with MPC5121 DIU rev 2.0 silicon. ··· 476 495 { 477 496 struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par; 478 497 struct diu_ad *ad = mfbi->ad; 479 - struct fsl_diu_data *machine_data = mfbi->parent; 480 - struct diu __iomem *hw = machine_data->diu_reg; 498 + struct fsl_diu_data *data = mfbi->parent; 499 + struct diu __iomem *hw = data->diu_reg; 481 500 482 501 switch (mfbi->index) { 483 502 case PLANE0: ··· 485 504 wr_reg_wa(&hw->desc[0], ad->paddr); 486 505 break; 487 506 case PLANE1_AOI0: 488 - cmfbi = machine_data->fsl_diu_info[2]->par; 507 + cmfbi = &data->mfb[2]; 489 508 if (hw->desc[1] != ad->paddr) { /* AOI0 closed */ 490 509 if (cmfbi->count > 0) /* AOI1 open */ 491 510 ad->next_ad = ··· 496 515 } 497 516 break; 498 517 case PLANE2_AOI0: 499 - cmfbi = machine_data->fsl_diu_info[4]->par; 518 + cmfbi = &data->mfb[4]; 500 519 if (hw->desc[2] != ad->paddr) { /* AOI0 closed */ 501 520 if (cmfbi->count > 0) /* AOI1 open */ 502 521 ad->next_ad = ··· 507 526 } 508 527 break; 509 528 case PLANE1_AOI1: 510 - pmfbi = machine_data->fsl_diu_info[1]->par; 529 + pmfbi = &data->mfb[1]; 511 530 ad->next_ad = 0; 512 - if (hw->desc[1] == machine_data->dummy_ad->paddr) 531 + if (hw->desc[1] == data->dummy_ad.paddr) 513 532 wr_reg_wa(&hw->desc[1], ad->paddr); 514 533 else /* AOI0 open */ 515 534 pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); 516 535 break; 517 536 case PLANE2_AOI1: 518 - pmfbi = machine_data->fsl_diu_info[3]->par; 537 + pmfbi = &data->mfb[3]; 519 538 ad->next_ad = 0; 520 - if (hw->desc[2] == machine_data->dummy_ad->paddr) 539 + if (hw->desc[2] == data->dummy_ad.paddr) 521 540 wr_reg_wa(&hw->desc[2], ad->paddr); 522 541 else /* AOI0 was open */ 523 542 pmfbi->ad->next_ad = cpu_to_le32(ad->paddr); ··· 529 548 { 530 549 struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par; 531 550 struct diu_ad *ad = mfbi->ad; 532 - struct fsl_diu_data *machine_data = mfbi->parent; 533 - struct diu __iomem *hw = machine_data->diu_reg; 551 + struct fsl_diu_data *data = mfbi->parent; 552 + struct diu __iomem *hw = data->diu_reg; 534 553 535 554 switch (mfbi->index) { 536 555 case PLANE0: 537 - if (hw->desc[0] != machine_data->dummy_ad->paddr) 538 - wr_reg_wa(&hw->desc[0], machine_data->dummy_ad->paddr); 556 + if (hw->desc[0] != data->dummy_ad.paddr) 557 + wr_reg_wa(&hw->desc[0], data->dummy_ad.paddr); 539 558 break; 540 559 case PLANE1_AOI0: 541 - cmfbi = machine_data->fsl_diu_info[2]->par; 560 + cmfbi = &data->mfb[2]; 542 561 if (cmfbi->count > 0) /* AOI1 is open */ 543 562 wr_reg_wa(&hw->desc[1], cmfbi->ad->paddr); 544 563 /* move AOI1 to the first */ 545 564 else /* AOI1 was closed */ 546 - wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr); 565 + wr_reg_wa(&hw->desc[1], data->dummy_ad.paddr); 547 566 /* close AOI 0 */ 548 567 break; 549 568 case PLANE2_AOI0: 550 - cmfbi = machine_data->fsl_diu_info[4]->par; 569 + cmfbi = &data->mfb[4]; 551 570 if (cmfbi->count > 0) /* AOI1 is open */ 552 571 wr_reg_wa(&hw->desc[2], cmfbi->ad->paddr); 553 572 /* move AOI1 to the first */ 554 573 else /* AOI1 was closed */ 555 - wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr); 574 + wr_reg_wa(&hw->desc[2], data->dummy_ad.paddr); 556 575 /* close AOI 0 */ 557 576 break; 558 577 case PLANE1_AOI1: 559 - pmfbi = machine_data->fsl_diu_info[1]->par; 578 + pmfbi = &data->mfb[1]; 560 579 if (hw->desc[1] != ad->paddr) { 561 580 /* AOI1 is not the first in the chain */ 562 581 if (pmfbi->count > 0) 563 582 /* AOI0 is open, must be the first */ 564 583 pmfbi->ad->next_ad = 0; 565 584 } else /* AOI1 is the first in the chain */ 566 - wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr); 585 + wr_reg_wa(&hw->desc[1], data->dummy_ad.paddr); 567 586 /* close AOI 1 */ 568 587 break; 569 588 case PLANE2_AOI1: 570 - pmfbi = machine_data->fsl_diu_info[3]->par; 589 + pmfbi = &data->mfb[3]; 571 590 if (hw->desc[2] != ad->paddr) { 572 591 /* AOI1 is not the first in the chain */ 573 592 if (pmfbi->count > 0) 574 593 /* AOI0 is open, must be the first */ 575 594 pmfbi->ad->next_ad = 0; 576 595 } else /* AOI1 is the first in the chain */ 577 - wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr); 596 + wr_reg_wa(&hw->desc[2], data->dummy_ad.paddr); 578 597 /* close AOI 1 */ 579 598 break; 580 599 } ··· 583 602 static void enable_lcdc(struct fb_info *info) 584 603 { 585 604 struct mfb_info *mfbi = info->par; 586 - struct fsl_diu_data *machine_data = mfbi->parent; 587 - struct diu __iomem *hw = machine_data->diu_reg; 605 + struct fsl_diu_data *data = mfbi->parent; 606 + struct diu __iomem *hw = data->diu_reg; 588 607 589 - if (!machine_data->fb_enabled) { 590 - out_be32(&hw->diu_mode, MFB_MODE1); 591 - machine_data->fb_enabled++; 592 - } 608 + out_be32(&hw->diu_mode, MFB_MODE1); 593 609 } 594 610 595 611 static void disable_lcdc(struct fb_info *info) 596 612 { 597 613 struct mfb_info *mfbi = info->par; 598 - struct fsl_diu_data *machine_data = mfbi->parent; 599 - struct diu __iomem *hw = machine_data->diu_reg; 614 + struct fsl_diu_data *data = mfbi->parent; 615 + struct diu __iomem *hw = data->diu_reg; 600 616 601 - if (machine_data->fb_enabled) { 602 - out_be32(&hw->diu_mode, 0); 603 - machine_data->fb_enabled = 0; 604 - } 617 + out_be32(&hw->diu_mode, 0); 605 618 } 606 619 607 620 static void adjust_aoi_size_position(struct fb_var_screeninfo *var, 608 621 struct fb_info *info) 609 622 { 610 623 struct mfb_info *lower_aoi_mfbi, *upper_aoi_mfbi, *mfbi = info->par; 611 - struct fsl_diu_data *machine_data = mfbi->parent; 624 + struct fsl_diu_data *data = mfbi->parent; 612 625 int available_height, upper_aoi_bottom; 613 626 enum mfb_index index = mfbi->index; 614 627 int lower_aoi_is_open, upper_aoi_is_open; 615 628 __u32 base_plane_width, base_plane_height, upper_aoi_height; 616 629 617 - base_plane_width = machine_data->fsl_diu_info[0]->var.xres; 618 - base_plane_height = machine_data->fsl_diu_info[0]->var.yres; 630 + base_plane_width = data->fsl_diu_info[0].var.xres; 631 + base_plane_height = data->fsl_diu_info[0].var.yres; 619 632 620 633 if (mfbi->x_aoi_d < 0) 621 634 mfbi->x_aoi_d = 0; ··· 624 649 break; 625 650 case PLANE1_AOI0: 626 651 case PLANE2_AOI0: 627 - lower_aoi_mfbi = machine_data->fsl_diu_info[index+1]->par; 652 + lower_aoi_mfbi = data->fsl_diu_info[index+1].par; 628 653 lower_aoi_is_open = lower_aoi_mfbi->count > 0 ? 1 : 0; 629 654 if (var->xres > base_plane_width) 630 655 var->xres = base_plane_width; ··· 642 667 break; 643 668 case PLANE1_AOI1: 644 669 case PLANE2_AOI1: 645 - upper_aoi_mfbi = machine_data->fsl_diu_info[index-1]->par; 646 - upper_aoi_height = 647 - machine_data->fsl_diu_info[index-1]->var.yres; 670 + upper_aoi_mfbi = data->fsl_diu_info[index-1].par; 671 + upper_aoi_height = data->fsl_diu_info[index-1].var.yres; 648 672 upper_aoi_bottom = upper_aoi_mfbi->y_aoi_d + upper_aoi_height; 649 673 upper_aoi_is_open = upper_aoi_mfbi->count > 0 ? 1 : 0; 650 674 if (var->xres > base_plane_width) ··· 783 809 { 784 810 struct fb_var_screeninfo *var = &info->var; 785 811 struct mfb_info *mfbi = info->par; 786 - struct fsl_diu_data *machine_data = mfbi->parent; 812 + struct fsl_diu_data *data = mfbi->parent; 787 813 struct diu __iomem *hw; 788 814 int i, j; 789 - char __iomem *cursor_base, *gamma_table_base; 815 + u8 *gamma_table_base; 790 816 791 817 u32 temp; 792 818 793 - hw = machine_data->diu_reg; 819 + hw = data->diu_reg; 794 820 795 - diu_ops.set_monitor_port(machine_data->monitor_port); 796 - gamma_table_base = machine_data->gamma.vaddr; 797 - cursor_base = machine_data->cursor.vaddr; 821 + diu_ops.set_monitor_port(data->monitor_port); 822 + gamma_table_base = data->gamma; 823 + 798 824 /* Prep for DIU init - gamma table, cursor table */ 799 825 800 826 for (i = 0; i <= 2; i++) 801 827 for (j = 0; j <= 255; j++) 802 828 *gamma_table_base++ = j; 803 829 804 - diu_ops.set_gamma_table(machine_data->monitor_port, 805 - machine_data->gamma.vaddr); 830 + if (diu_ops.set_gamma_table) 831 + diu_ops.set_gamma_table(data->monitor_port, data->gamma); 806 832 807 833 disable_lcdc(info); 808 834 809 835 /* Program DIU registers */ 810 836 811 - out_be32(&hw->gamma, machine_data->gamma.paddr); 812 - out_be32(&hw->cursor, machine_data->cursor.paddr); 837 + out_be32(&hw->gamma, DMA_ADDR(data, gamma)); 838 + out_be32(&hw->cursor, DMA_ADDR(data, cursor)); 813 839 814 840 out_be32(&hw->bgnd, 0x007F7F7F); /* BGND */ 815 841 out_be32(&hw->bgnd_wb, 0); /* BGND_WB */ ··· 844 870 845 871 static int map_video_memory(struct fb_info *info) 846 872 { 847 - phys_addr_t phys; 848 873 u32 smem_len = info->fix.line_length * info->var.yres_virtual; 874 + void *p; 849 875 850 - info->screen_base = fsl_diu_alloc(smem_len, &phys); 851 - if (info->screen_base == NULL) { 876 + p = alloc_pages_exact(smem_len, GFP_DMA | __GFP_ZERO); 877 + if (!p) { 852 878 dev_err(info->dev, "unable to allocate fb memory\n"); 853 879 return -ENOMEM; 854 880 } 855 881 mutex_lock(&info->mm_lock); 856 - info->fix.smem_start = (unsigned long) phys; 882 + info->screen_base = p; 883 + info->fix.smem_start = virt_to_phys(info->screen_base); 857 884 info->fix.smem_len = smem_len; 858 885 mutex_unlock(&info->mm_lock); 859 886 info->screen_size = info->fix.smem_len; ··· 864 889 865 890 static void unmap_video_memory(struct fb_info *info) 866 891 { 867 - fsl_diu_free(info->screen_base, info->fix.smem_len); 892 + void *p = info->screen_base; 893 + size_t l = info->fix.smem_len; 894 + 868 895 mutex_lock(&info->mm_lock); 869 896 info->screen_base = NULL; 870 897 info->fix.smem_start = 0; 871 898 info->fix.smem_len = 0; 872 899 mutex_unlock(&info->mm_lock); 900 + 901 + if (p) 902 + free_pages_exact(p, l); 873 903 } 874 904 875 905 /* ··· 893 913 return 0; 894 914 } 895 915 916 + /** 917 + * fsl_diu_get_pixel_format: return the pixel format for a given color depth 918 + * 919 + * The pixel format is a 32-bit value that determine which bits in each 920 + * pixel are to be used for each color. This is the default function used 921 + * if the platform does not define its own version. 922 + */ 923 + static u32 fsl_diu_get_pixel_format(unsigned int bits_per_pixel) 924 + { 925 + #define PF_BYTE_F 0x10000000 926 + #define PF_ALPHA_C_MASK 0x0E000000 927 + #define PF_ALPHA_C_SHIFT 25 928 + #define PF_BLUE_C_MASK 0x01800000 929 + #define PF_BLUE_C_SHIFT 23 930 + #define PF_GREEN_C_MASK 0x00600000 931 + #define PF_GREEN_C_SHIFT 21 932 + #define PF_RED_C_MASK 0x00180000 933 + #define PF_RED_C_SHIFT 19 934 + #define PF_PALETTE 0x00040000 935 + #define PF_PIXEL_S_MASK 0x00030000 936 + #define PF_PIXEL_S_SHIFT 16 937 + #define PF_COMP_3_MASK 0x0000F000 938 + #define PF_COMP_3_SHIFT 12 939 + #define PF_COMP_2_MASK 0x00000F00 940 + #define PF_COMP_2_SHIFT 8 941 + #define PF_COMP_1_MASK 0x000000F0 942 + #define PF_COMP_1_SHIFT 4 943 + #define PF_COMP_0_MASK 0x0000000F 944 + #define PF_COMP_0_SHIFT 0 945 + 946 + #define MAKE_PF(alpha, red, blue, green, size, c0, c1, c2, c3) \ 947 + cpu_to_le32(PF_BYTE_F | (alpha << PF_ALPHA_C_SHIFT) | \ 948 + (blue << PF_BLUE_C_SHIFT) | (green << PF_GREEN_C_SHIFT) | \ 949 + (red << PF_RED_C_SHIFT) | (c3 << PF_COMP_3_SHIFT) | \ 950 + (c2 << PF_COMP_2_SHIFT) | (c1 << PF_COMP_1_SHIFT) | \ 951 + (c0 << PF_COMP_0_SHIFT) | (size << PF_PIXEL_S_SHIFT)) 952 + 953 + switch (bits_per_pixel) { 954 + case 32: 955 + /* 0x88883316 */ 956 + return MAKE_PF(3, 2, 0, 1, 3, 8, 8, 8, 8); 957 + case 24: 958 + /* 0x88082219 */ 959 + return MAKE_PF(4, 0, 1, 2, 2, 0, 8, 8, 8); 960 + case 16: 961 + /* 0x65053118 */ 962 + return MAKE_PF(4, 2, 1, 0, 1, 5, 6, 5, 0); 963 + default: 964 + pr_err("fsl-diu: unsupported color depth %u\n", bits_per_pixel); 965 + return 0; 966 + } 967 + } 968 + 896 969 /* 897 970 * Using the fb_var_screeninfo in fb_info we set the resolution of this 898 971 * particular framebuffer. This function alters the fb_fix_screeninfo stored ··· 959 926 unsigned long len; 960 927 struct fb_var_screeninfo *var = &info->var; 961 928 struct mfb_info *mfbi = info->par; 962 - struct fsl_diu_data *machine_data = mfbi->parent; 929 + struct fsl_diu_data *data = mfbi->parent; 963 930 struct diu_ad *ad = mfbi->ad; 964 931 struct diu __iomem *hw; 965 932 966 - hw = machine_data->diu_reg; 933 + hw = data->diu_reg; 967 934 968 935 set_fix(info); 969 936 mfbi->cursor_reset = 1; ··· 981 948 } 982 949 } 983 950 984 - ad->pix_fmt = diu_ops.get_pixel_format(machine_data->monitor_port, 985 - var->bits_per_pixel); 951 + if (diu_ops.get_pixel_format) 952 + ad->pix_fmt = diu_ops.get_pixel_format(data->monitor_port, 953 + var->bits_per_pixel); 954 + else 955 + ad->pix_fmt = fsl_diu_get_pixel_format(var->bits_per_pixel); 956 + 986 957 ad->addr = cpu_to_le32(info->fix.smem_start); 987 958 ad->src_size_g_alpha = cpu_to_le32((var->yres_virtual << 12) | 988 959 var->xres_virtual) | mfbi->g_alpha; ··· 1245 1208 .fb_release = fsl_diu_release, 1246 1209 }; 1247 1210 1248 - static int init_fbinfo(struct fb_info *info) 1249 - { 1250 - struct mfb_info *mfbi = info->par; 1251 - 1252 - info->device = NULL; 1253 - info->var.activate = FB_ACTIVATE_NOW; 1254 - info->fbops = &fsl_diu_ops; 1255 - info->flags = FBINFO_FLAG_DEFAULT; 1256 - info->pseudo_palette = &mfbi->pseudo_palette; 1257 - 1258 - /* Allocate colormap */ 1259 - fb_alloc_cmap(&info->cmap, 16, 0); 1260 - return 0; 1261 - } 1262 - 1263 1211 static int __devinit install_fb(struct fb_info *info) 1264 1212 { 1265 1213 int rc; ··· 1254 1232 unsigned int dbsize = ARRAY_SIZE(fsl_diu_mode_db); 1255 1233 int has_default_mode = 1; 1256 1234 1257 - if (init_fbinfo(info)) 1258 - return -EINVAL; 1235 + info->var.activate = FB_ACTIVATE_NOW; 1236 + info->fbops = &fsl_diu_ops; 1237 + info->flags = FBINFO_DEFAULT | FBINFO_VIRTFB | FBINFO_PARTIAL_PAN_OK | 1238 + FBINFO_READS_FAST; 1239 + info->pseudo_palette = mfbi->pseudo_palette; 1240 + 1241 + rc = fb_alloc_cmap(&info->cmap, 16, 0); 1242 + if (rc) 1243 + return rc; 1259 1244 1260 1245 if (mfbi->index == PLANE0) { 1261 1246 if (mfbi->edid_data) { ··· 1388 1359 return IRQ_NONE; 1389 1360 } 1390 1361 1391 - static int request_irq_local(struct fsl_diu_data *machine_data) 1362 + static int request_irq_local(struct fsl_diu_data *data) 1392 1363 { 1393 - struct diu __iomem *hw = machine_data->diu_reg; 1364 + struct diu __iomem *hw = data->diu_reg; 1394 1365 u32 ints; 1395 1366 int ret; 1396 1367 1397 1368 /* Read to clear the status */ 1398 1369 in_be32(&hw->int_status); 1399 1370 1400 - ret = request_irq(machine_data->irq, fsl_diu_isr, 0, "fsl-diu-fb", hw); 1371 + ret = request_irq(data->irq, fsl_diu_isr, 0, "fsl-diu-fb", hw); 1401 1372 if (!ret) { 1402 1373 ints = INT_PARERR | INT_LS_BF_VS; 1403 1374 #if !defined(CONFIG_NOT_COHERENT_CACHE) ··· 1412 1383 return ret; 1413 1384 } 1414 1385 1415 - static void free_irq_local(struct fsl_diu_data *machine_data) 1386 + static void free_irq_local(struct fsl_diu_data *data) 1416 1387 { 1417 - struct diu __iomem *hw = machine_data->diu_reg; 1388 + struct diu __iomem *hw = data->diu_reg; 1418 1389 1419 1390 /* Disable all LCDC interrupt */ 1420 1391 out_be32(&hw->int_mask, 0x1f); 1421 1392 1422 - free_irq(machine_data->irq, NULL); 1393 + free_irq(data->irq, NULL); 1423 1394 } 1424 1395 1425 1396 #ifdef CONFIG_PM ··· 1429 1400 */ 1430 1401 static int fsl_diu_suspend(struct platform_device *ofdev, pm_message_t state) 1431 1402 { 1432 - struct fsl_diu_data *machine_data; 1403 + struct fsl_diu_data *data; 1433 1404 1434 - machine_data = dev_get_drvdata(&ofdev->dev); 1435 - disable_lcdc(machine_data->fsl_diu_info[0]); 1405 + data = dev_get_drvdata(&ofdev->dev); 1406 + disable_lcdc(data->fsl_diu_info[0]); 1436 1407 1437 1408 return 0; 1438 1409 } 1439 1410 1440 1411 static int fsl_diu_resume(struct platform_device *ofdev) 1441 1412 { 1442 - struct fsl_diu_data *machine_data; 1413 + struct fsl_diu_data *data; 1443 1414 1444 - machine_data = dev_get_drvdata(&ofdev->dev); 1445 - enable_lcdc(machine_data->fsl_diu_info[0]); 1415 + data = dev_get_drvdata(&ofdev->dev); 1416 + enable_lcdc(data->fsl_diu_info[0]); 1446 1417 1447 1418 return 0; 1448 1419 } ··· 1452 1423 #define fsl_diu_resume NULL 1453 1424 #endif /* CONFIG_PM */ 1454 1425 1455 - /* Align to 64-bit(8-byte), 32-byte, etc. */ 1456 - static int allocate_buf(struct device *dev, struct diu_addr *buf, u32 size, 1457 - u32 bytes_align) 1458 - { 1459 - u32 offset; 1460 - dma_addr_t mask; 1461 - 1462 - buf->vaddr = 1463 - dma_alloc_coherent(dev, size + bytes_align, &buf->paddr, 1464 - GFP_DMA | __GFP_ZERO); 1465 - if (!buf->vaddr) 1466 - return -ENOMEM; 1467 - 1468 - mask = bytes_align - 1; 1469 - offset = buf->paddr & mask; 1470 - if (offset) { 1471 - buf->offset = bytes_align - offset; 1472 - buf->paddr = buf->paddr + offset; 1473 - } else 1474 - buf->offset = 0; 1475 - 1476 - return 0; 1477 - } 1478 - 1479 - static void free_buf(struct device *dev, struct diu_addr *buf, u32 size, 1480 - u32 bytes_align) 1481 - { 1482 - dma_free_coherent(dev, size + bytes_align, buf->vaddr, 1483 - buf->paddr - buf->offset); 1484 - } 1485 - 1486 1426 static ssize_t store_monitor(struct device *device, 1487 1427 struct device_attribute *attr, const char *buf, size_t count) 1488 1428 { 1489 1429 enum fsl_diu_monitor_port old_monitor_port; 1490 - struct fsl_diu_data *machine_data = 1430 + struct fsl_diu_data *data = 1491 1431 container_of(attr, struct fsl_diu_data, dev_attr); 1492 1432 1493 - old_monitor_port = machine_data->monitor_port; 1494 - machine_data->monitor_port = fsl_diu_name_to_port(buf); 1433 + old_monitor_port = data->monitor_port; 1434 + data->monitor_port = fsl_diu_name_to_port(buf); 1495 1435 1496 - if (old_monitor_port != machine_data->monitor_port) { 1436 + if (old_monitor_port != data->monitor_port) { 1497 1437 /* All AOIs need adjust pixel format 1498 1438 * fsl_diu_set_par only change the pixsel format here 1499 1439 * unlikely to fail. */ 1500 - fsl_diu_set_par(machine_data->fsl_diu_info[0]); 1501 - fsl_diu_set_par(machine_data->fsl_diu_info[1]); 1502 - fsl_diu_set_par(machine_data->fsl_diu_info[2]); 1503 - fsl_diu_set_par(machine_data->fsl_diu_info[3]); 1504 - fsl_diu_set_par(machine_data->fsl_diu_info[4]); 1440 + unsigned int i; 1441 + 1442 + for (i=0; i < NUM_AOIS; i++) 1443 + fsl_diu_set_par(&data->fsl_diu_info[i]); 1505 1444 } 1506 1445 return count; 1507 1446 } ··· 1477 1480 static ssize_t show_monitor(struct device *device, 1478 1481 struct device_attribute *attr, char *buf) 1479 1482 { 1480 - struct fsl_diu_data *machine_data = 1483 + struct fsl_diu_data *data = 1481 1484 container_of(attr, struct fsl_diu_data, dev_attr); 1482 1485 1483 - switch (machine_data->monitor_port) { 1486 + switch (data->monitor_port) { 1484 1487 case FSL_DIU_PORT_DVI: 1485 1488 return sprintf(buf, "DVI\n"); 1486 1489 case FSL_DIU_PORT_LVDS: ··· 1496 1499 { 1497 1500 struct device_node *np = pdev->dev.of_node; 1498 1501 struct mfb_info *mfbi; 1499 - phys_addr_t dummy_ad_addr = 0; 1500 - int ret, i, error = 0; 1501 - struct fsl_diu_data *machine_data; 1502 + struct fsl_diu_data *data; 1502 1503 int diu_mode; 1504 + dma_addr_t dma_addr; /* DMA addr of fsl_diu_data struct */ 1505 + unsigned int i; 1506 + int ret; 1503 1507 1504 - machine_data = kzalloc(sizeof(struct fsl_diu_data), GFP_KERNEL); 1505 - if (!machine_data) 1508 + data = dma_alloc_coherent(&pdev->dev, sizeof(struct fsl_diu_data), 1509 + &dma_addr, GFP_DMA | __GFP_ZERO); 1510 + if (!data) 1506 1511 return -ENOMEM; 1512 + data->dma_addr = dma_addr; 1507 1513 1508 - spin_lock_init(&machine_data->reg_lock); 1514 + /* 1515 + * dma_alloc_coherent() uses a page allocator, so the address is 1516 + * always page-aligned. We need the memory to be 32-byte aligned, 1517 + * so that's good. However, if one day the allocator changes, we 1518 + * need to catch that. It's not worth the effort to handle unaligned 1519 + * alloctions now because it's highly unlikely to ever be a problem. 1520 + */ 1521 + if ((unsigned long)data & 31) { 1522 + dev_err(&pdev->dev, "misaligned allocation"); 1523 + ret = -ENOMEM; 1524 + goto error; 1525 + } 1509 1526 1510 - for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) { 1511 - machine_data->fsl_diu_info[i] = 1512 - framebuffer_alloc(sizeof(struct mfb_info), &pdev->dev); 1513 - if (!machine_data->fsl_diu_info[i]) { 1514 - dev_err(&pdev->dev, "cannot allocate memory\n"); 1515 - ret = -ENOMEM; 1516 - goto error2; 1517 - } 1518 - mfbi = machine_data->fsl_diu_info[i]->par; 1527 + spin_lock_init(&data->reg_lock); 1528 + 1529 + for (i = 0; i < NUM_AOIS; i++) { 1530 + struct fb_info *info = &data->fsl_diu_info[i]; 1531 + 1532 + info->device = &pdev->dev; 1533 + info->par = &data->mfb[i]; 1534 + 1535 + /* 1536 + * We store the physical address of the AD in the reserved 1537 + * 'paddr' field of the AD itself. 1538 + */ 1539 + data->ad[i].paddr = DMA_ADDR(data, ad[i]); 1540 + 1541 + info->fix.smem_start = 0; 1542 + 1543 + /* Initialize the AOI data structure */ 1544 + mfbi = info->par; 1519 1545 memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info)); 1520 - mfbi->parent = machine_data; 1546 + mfbi->parent = data; 1547 + mfbi->ad = &data->ad[i]; 1521 1548 1522 1549 if (mfbi->index == PLANE0) { 1523 1550 const u8 *prop; ··· 1555 1534 } 1556 1535 } 1557 1536 1558 - machine_data->diu_reg = of_iomap(np, 0); 1559 - if (!machine_data->diu_reg) { 1537 + data->diu_reg = of_iomap(np, 0); 1538 + if (!data->diu_reg) { 1560 1539 dev_err(&pdev->dev, "cannot map DIU registers\n"); 1561 1540 ret = -EFAULT; 1562 - goto error2; 1541 + goto error; 1563 1542 } 1564 1543 1565 - diu_mode = in_be32(&machine_data->diu_reg->diu_mode); 1544 + diu_mode = in_be32(&data->diu_reg->diu_mode); 1566 1545 if (diu_mode == MFB_MODE0) 1567 - out_be32(&machine_data->diu_reg->diu_mode, 0); /* disable DIU */ 1546 + out_be32(&data->diu_reg->diu_mode, 0); /* disable DIU */ 1568 1547 1569 1548 /* Get the IRQ of the DIU */ 1570 - machine_data->irq = irq_of_parse_and_map(np, 0); 1549 + data->irq = irq_of_parse_and_map(np, 0); 1571 1550 1572 - if (!machine_data->irq) { 1551 + if (!data->irq) { 1573 1552 dev_err(&pdev->dev, "could not get DIU IRQ\n"); 1574 1553 ret = -EINVAL; 1575 1554 goto error; 1576 1555 } 1577 - machine_data->monitor_port = monitor_port; 1556 + data->monitor_port = monitor_port; 1578 1557 1579 - /* Area descriptor memory pool aligns to 64-bit boundary */ 1580 - if (allocate_buf(&pdev->dev, &machine_data->ad, 1581 - sizeof(struct diu_ad) * FSL_AOI_NUM, 8)) 1582 - return -ENOMEM; 1583 - 1584 - /* Get memory for Gamma Table - 32-byte aligned memory */ 1585 - if (allocate_buf(&pdev->dev, &machine_data->gamma, 768, 32)) { 1586 - ret = -ENOMEM; 1587 - goto error; 1588 - } 1589 - 1590 - /* For performance, cursor bitmap buffer aligns to 32-byte boundary */ 1591 - if (allocate_buf(&pdev->dev, &machine_data->cursor, 1592 - MAX_CURS * MAX_CURS * 2, 32)) { 1593 - ret = -ENOMEM; 1594 - goto error; 1595 - } 1596 - 1597 - i = ARRAY_SIZE(machine_data->fsl_diu_info); 1598 - machine_data->dummy_ad = (struct diu_ad *)((u32)machine_data->ad.vaddr + 1599 - machine_data->ad.offset) + i; 1600 - machine_data->dummy_ad->paddr = machine_data->ad.paddr + 1601 - i * sizeof(struct diu_ad); 1602 - machine_data->dummy_aoi_virt = fsl_diu_alloc(64, &dummy_ad_addr); 1603 - if (!machine_data->dummy_aoi_virt) { 1604 - ret = -ENOMEM; 1605 - goto error; 1606 - } 1607 - machine_data->dummy_ad->addr = cpu_to_le32(dummy_ad_addr); 1608 - machine_data->dummy_ad->pix_fmt = 0x88882317; 1609 - machine_data->dummy_ad->src_size_g_alpha = cpu_to_le32((4 << 12) | 4); 1610 - machine_data->dummy_ad->aoi_size = cpu_to_le32((4 << 16) | 2); 1611 - machine_data->dummy_ad->offset_xyi = 0; 1612 - machine_data->dummy_ad->offset_xyd = 0; 1613 - machine_data->dummy_ad->next_ad = 0; 1558 + /* Initialize the dummy Area Descriptor */ 1559 + data->dummy_ad.addr = cpu_to_le32(DMA_ADDR(data, dummy_aoi)); 1560 + data->dummy_ad.pix_fmt = 0x88882317; 1561 + data->dummy_ad.src_size_g_alpha = cpu_to_le32((4 << 12) | 4); 1562 + data->dummy_ad.aoi_size = cpu_to_le32((4 << 16) | 2); 1563 + data->dummy_ad.offset_xyi = 0; 1564 + data->dummy_ad.offset_xyd = 0; 1565 + data->dummy_ad.next_ad = 0; 1566 + data->dummy_ad.paddr = DMA_ADDR(data, dummy_ad); 1614 1567 1615 1568 /* 1616 1569 * Let DIU display splash screen if it was pre-initialized 1617 1570 * by the bootloader, set dummy area descriptor otherwise. 1618 1571 */ 1619 1572 if (diu_mode == MFB_MODE0) 1620 - out_be32(&machine_data->diu_reg->desc[0], 1621 - machine_data->dummy_ad->paddr); 1573 + out_be32(&data->diu_reg->desc[0], data->dummy_ad.paddr); 1622 1574 1623 - out_be32(&machine_data->diu_reg->desc[1], machine_data->dummy_ad->paddr); 1624 - out_be32(&machine_data->diu_reg->desc[2], machine_data->dummy_ad->paddr); 1575 + out_be32(&data->diu_reg->desc[1], data->dummy_ad.paddr); 1576 + out_be32(&data->diu_reg->desc[2], data->dummy_ad.paddr); 1625 1577 1626 - for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) { 1627 - machine_data->fsl_diu_info[i]->fix.smem_start = 0; 1628 - mfbi = machine_data->fsl_diu_info[i]->par; 1629 - mfbi->ad = (struct diu_ad *)((u32)machine_data->ad.vaddr 1630 - + machine_data->ad.offset) + i; 1631 - mfbi->ad->paddr = 1632 - machine_data->ad.paddr + i * sizeof(struct diu_ad); 1633 - ret = install_fb(machine_data->fsl_diu_info[i]); 1578 + for (i = 0; i < NUM_AOIS; i++) { 1579 + ret = install_fb(&data->fsl_diu_info[i]); 1634 1580 if (ret) { 1635 1581 dev_err(&pdev->dev, "could not register fb %d\n", i); 1636 1582 goto error; 1637 1583 } 1638 1584 } 1639 1585 1640 - if (request_irq_local(machine_data)) { 1586 + if (request_irq_local(data)) { 1641 1587 dev_err(&pdev->dev, "could not claim irq\n"); 1642 1588 goto error; 1643 1589 } 1644 1590 1645 - sysfs_attr_init(&machine_data->dev_attr.attr); 1646 - machine_data->dev_attr.attr.name = "monitor"; 1647 - machine_data->dev_attr.attr.mode = S_IRUGO|S_IWUSR; 1648 - machine_data->dev_attr.show = show_monitor; 1649 - machine_data->dev_attr.store = store_monitor; 1650 - error = device_create_file(machine_data->fsl_diu_info[0]->dev, 1651 - &machine_data->dev_attr); 1652 - if (error) { 1591 + sysfs_attr_init(&data->dev_attr.attr); 1592 + data->dev_attr.attr.name = "monitor"; 1593 + data->dev_attr.attr.mode = S_IRUGO|S_IWUSR; 1594 + data->dev_attr.show = show_monitor; 1595 + data->dev_attr.store = store_monitor; 1596 + ret = device_create_file(&pdev->dev, &data->dev_attr); 1597 + if (ret) { 1653 1598 dev_err(&pdev->dev, "could not create sysfs file %s\n", 1654 - machine_data->dev_attr.attr.name); 1599 + data->dev_attr.attr.name); 1655 1600 } 1656 1601 1657 - dev_set_drvdata(&pdev->dev, machine_data); 1602 + dev_set_drvdata(&pdev->dev, data); 1658 1603 return 0; 1659 1604 1660 1605 error: 1661 - for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) 1662 - uninstall_fb(machine_data->fsl_diu_info[i]); 1606 + for (i = 0; i < NUM_AOIS; i++) 1607 + uninstall_fb(&data->fsl_diu_info[i]); 1663 1608 1664 - if (machine_data->ad.vaddr) 1665 - free_buf(&pdev->dev, &machine_data->ad, 1666 - sizeof(struct diu_ad) * FSL_AOI_NUM, 8); 1667 - if (machine_data->gamma.vaddr) 1668 - free_buf(&pdev->dev, &machine_data->gamma, 768, 32); 1669 - if (machine_data->cursor.vaddr) 1670 - free_buf(&pdev->dev, &machine_data->cursor, 1671 - MAX_CURS * MAX_CURS * 2, 32); 1672 - if (machine_data->dummy_aoi_virt) 1673 - fsl_diu_free(machine_data->dummy_aoi_virt, 64); 1674 - iounmap(machine_data->diu_reg); 1609 + iounmap(data->diu_reg); 1675 1610 1676 - error2: 1677 - for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) 1678 - if (machine_data->fsl_diu_info[i]) 1679 - framebuffer_release(machine_data->fsl_diu_info[i]); 1680 - kfree(machine_data); 1611 + dma_free_coherent(&pdev->dev, sizeof(struct fsl_diu_data), data, 1612 + data->dma_addr); 1681 1613 1682 1614 return ret; 1683 1615 } 1684 1616 1685 1617 static int fsl_diu_remove(struct platform_device *pdev) 1686 1618 { 1687 - struct fsl_diu_data *machine_data; 1619 + struct fsl_diu_data *data; 1688 1620 int i; 1689 1621 1690 - machine_data = dev_get_drvdata(&pdev->dev); 1691 - disable_lcdc(machine_data->fsl_diu_info[0]); 1692 - free_irq_local(machine_data); 1693 - for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) 1694 - uninstall_fb(machine_data->fsl_diu_info[i]); 1695 - if (machine_data->ad.vaddr) 1696 - free_buf(&pdev->dev, &machine_data->ad, 1697 - sizeof(struct diu_ad) * FSL_AOI_NUM, 8); 1698 - if (machine_data->gamma.vaddr) 1699 - free_buf(&pdev->dev, &machine_data->gamma, 768, 32); 1700 - if (machine_data->cursor.vaddr) 1701 - free_buf(&pdev->dev, &machine_data->cursor, 1702 - MAX_CURS * MAX_CURS * 2, 32); 1703 - if (machine_data->dummy_aoi_virt) 1704 - fsl_diu_free(machine_data->dummy_aoi_virt, 64); 1705 - iounmap(machine_data->diu_reg); 1706 - for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) 1707 - if (machine_data->fsl_diu_info[i]) 1708 - framebuffer_release(machine_data->fsl_diu_info[i]); 1709 - kfree(machine_data); 1622 + data = dev_get_drvdata(&pdev->dev); 1623 + disable_lcdc(&data->fsl_diu_info[0]); 1624 + free_irq_local(data); 1625 + 1626 + for (i = 0; i < NUM_AOIS; i++) 1627 + uninstall_fb(&data->fsl_diu_info[i]); 1628 + 1629 + iounmap(data->diu_reg); 1630 + 1631 + dma_free_coherent(&pdev->dev, sizeof(struct fsl_diu_data), data, 1632 + data->dma_addr); 1710 1633 1711 1634 return 0; 1712 1635 }
+2 -2
drivers/video/grvga.c
··· 70 70 } 71 71 }; 72 72 73 - static struct fb_fix_screeninfo grvga_fix __initdata = { 73 + static struct fb_fix_screeninfo grvga_fix __devinitdata = { 74 74 .id = "AG SVGACTRL", 75 75 .type = FB_TYPE_PACKED_PIXELS, 76 76 .visual = FB_VISUAL_PSEUDOCOLOR, ··· 267 267 .fb_imageblit = cfb_imageblit 268 268 }; 269 269 270 - static int __init grvga_parse_custom(char *options, 270 + static int __devinit grvga_parse_custom(char *options, 271 271 struct fb_var_screeninfo *screendata) 272 272 { 273 273 char *this_opt;
+8 -8
drivers/video/i810/i810_main.c
··· 135 135 static char *mode_option __devinitdata = NULL; 136 136 static int vram __devinitdata = 4; 137 137 static int bpp __devinitdata = 8; 138 - static int mtrr __devinitdata; 139 - static int accel __devinitdata; 138 + static bool mtrr __devinitdata; 139 + static bool accel __devinitdata; 140 140 static int hsync1 __devinitdata; 141 141 static int hsync2 __devinitdata; 142 142 static int vsync1 __devinitdata; ··· 144 144 static int xres __devinitdata; 145 145 static int yres; 146 146 static int vyres __devinitdata; 147 - static int sync __devinitdata; 148 - static int extvga __devinitdata; 149 - static int dcolor __devinitdata; 150 - static int ddc3 __devinitdata = 2; 147 + static bool sync __devinitdata; 148 + static bool extvga __devinitdata; 149 + static bool dcolor __devinitdata; 150 + static bool ddc3 __devinitdata; 151 151 152 152 /*------------------------------------------------------------*/ 153 153 ··· 1776 1776 if (sync) 1777 1777 par->dev_flags |= ALWAYS_SYNC; 1778 1778 1779 - par->ddc_num = ddc3; 1779 + par->ddc_num = (ddc3 ? 3 : 2); 1780 1780 1781 1781 if (bpp < 8) 1782 1782 bpp = 8; ··· 1999 1999 else if (!strncmp(this_opt, "dcolor", 6)) 2000 2000 dcolor = 1; 2001 2001 else if (!strncmp(this_opt, "ddc3", 4)) 2002 - ddc3 = 3; 2002 + ddc3 = true; 2003 2003 else 2004 2004 mode_option = this_opt; 2005 2005 }
-1
drivers/video/matrox/matroxfb_base.c
··· 147 147 39721L,48L,16L,33L,10L, 148 148 96L,2L,~0, /* No sync info */ 149 149 FB_VMODE_NONINTERLACED, 150 - 0, {0,0,0,0,0} 151 150 }; 152 151 153 152
-1
drivers/video/matrox/matroxfb_crtc2.c
··· 593 593 39721L,48L,16L,33L,10L, 594 594 96L,2,0, /* no sync info */ 595 595 FB_VMODE_NONINTERLACED, 596 - 0, {0,0,0,0,0} 597 596 }; 598 597 599 598 static int matroxfb_dh_regit(const struct matrox_fb_info *minfo,
+1 -12
drivers/video/mbx/mbxfb.c
··· 1053 1053 }, 1054 1054 }; 1055 1055 1056 - int __devinit mbxfb_init(void) 1057 - { 1058 - return platform_driver_register(&mbxfb_driver); 1059 - } 1060 - 1061 - static void __devexit mbxfb_exit(void) 1062 - { 1063 - platform_driver_unregister(&mbxfb_driver); 1064 - } 1065 - 1066 - module_init(mbxfb_init); 1067 - module_exit(mbxfb_exit); 1056 + module_platform_driver(mbxfb_driver); 1068 1057 1069 1058 MODULE_DESCRIPTION("loadable framebuffer driver for Marathon device"); 1070 1059 MODULE_AUTHOR("Mike Rapoport, Compulab");
+1 -12
drivers/video/mxsfb.c
··· 902 902 }, 903 903 }; 904 904 905 - static int __init mxsfb_init(void) 906 - { 907 - return platform_driver_register(&mxsfb_driver); 908 - } 909 - 910 - static void __exit mxsfb_exit(void) 911 - { 912 - platform_driver_unregister(&mxsfb_driver); 913 - } 914 - 915 - module_init(mxsfb_init); 916 - module_exit(mxsfb_exit); 905 + module_platform_driver(mxsfb_driver); 917 906 918 907 MODULE_DESCRIPTION("Freescale mxs framebuffer driver"); 919 908 MODULE_AUTHOR("Sascha Hauer, Pengutronix");
+1 -12
drivers/video/nuc900fb.c
··· 762 762 }, 763 763 }; 764 764 765 - int __devinit nuc900fb_init(void) 766 - { 767 - return platform_driver_register(&nuc900fb_driver); 768 - } 769 - 770 - static void __exit nuc900fb_cleanup(void) 771 - { 772 - platform_driver_unregister(&nuc900fb_driver); 773 - } 774 - 775 - module_init(nuc900fb_init); 776 - module_exit(nuc900fb_cleanup); 765 + module_platform_driver(nuc900fb_driver); 777 766 778 767 MODULE_DESCRIPTION("Framebuffer driver for the NUC900"); 779 768 MODULE_LICENSE("GPL");
+2 -13
drivers/video/omap/lcd_ams_delta.c
··· 198 198 return 0; 199 199 } 200 200 201 - struct platform_driver ams_delta_panel_driver = { 201 + static struct platform_driver ams_delta_panel_driver = { 202 202 .probe = ams_delta_panel_probe, 203 203 .remove = ams_delta_panel_remove, 204 204 .suspend = ams_delta_panel_suspend, ··· 209 209 }, 210 210 }; 211 211 212 - static int __init ams_delta_panel_drv_init(void) 213 - { 214 - return platform_driver_register(&ams_delta_panel_driver); 215 - } 216 - 217 - static void __exit ams_delta_panel_drv_cleanup(void) 218 - { 219 - platform_driver_unregister(&ams_delta_panel_driver); 220 - } 221 - 222 - module_init(ams_delta_panel_drv_init); 223 - module_exit(ams_delta_panel_drv_cleanup); 212 + module_platform_driver(ams_delta_panel_driver);
+2 -14
drivers/video/omap/lcd_h3.c
··· 113 113 return 0; 114 114 } 115 115 116 - struct platform_driver h3_panel_driver = { 116 + static struct platform_driver h3_panel_driver = { 117 117 .probe = h3_panel_probe, 118 118 .remove = h3_panel_remove, 119 119 .suspend = h3_panel_suspend, ··· 124 124 }, 125 125 }; 126 126 127 - static int __init h3_panel_drv_init(void) 128 - { 129 - return platform_driver_register(&h3_panel_driver); 130 - } 131 - 132 - static void __exit h3_panel_drv_cleanup(void) 133 - { 134 - platform_driver_unregister(&h3_panel_driver); 135 - } 136 - 137 - module_init(h3_panel_drv_init); 138 - module_exit(h3_panel_drv_cleanup); 139 - 127 + module_platform_driver(h3_panel_driver);
+2 -14
drivers/video/omap/lcd_htcherald.c
··· 104 104 return 0; 105 105 } 106 106 107 - struct platform_driver htcherald_panel_driver = { 107 + static struct platform_driver htcherald_panel_driver = { 108 108 .probe = htcherald_panel_probe, 109 109 .remove = htcherald_panel_remove, 110 110 .suspend = htcherald_panel_suspend, ··· 115 115 }, 116 116 }; 117 117 118 - static int __init htcherald_panel_drv_init(void) 119 - { 120 - return platform_driver_register(&htcherald_panel_driver); 121 - } 122 - 123 - static void __exit htcherald_panel_drv_cleanup(void) 124 - { 125 - platform_driver_unregister(&htcherald_panel_driver); 126 - } 127 - 128 - module_init(htcherald_panel_drv_init); 129 - module_exit(htcherald_panel_drv_cleanup); 130 - 118 + module_platform_driver(htcherald_panel_driver);
+2 -14
drivers/video/omap/lcd_inn1510.c
··· 98 98 return 0; 99 99 } 100 100 101 - struct platform_driver innovator1510_panel_driver = { 101 + static struct platform_driver innovator1510_panel_driver = { 102 102 .probe = innovator1510_panel_probe, 103 103 .remove = innovator1510_panel_remove, 104 104 .suspend = innovator1510_panel_suspend, ··· 109 109 }, 110 110 }; 111 111 112 - static int __init innovator1510_panel_drv_init(void) 113 - { 114 - return platform_driver_register(&innovator1510_panel_driver); 115 - } 116 - 117 - static void __exit innovator1510_panel_drv_cleanup(void) 118 - { 119 - platform_driver_unregister(&innovator1510_panel_driver); 120 - } 121 - 122 - module_init(innovator1510_panel_drv_init); 123 - module_exit(innovator1510_panel_drv_cleanup); 124 - 112 + module_platform_driver(innovator1510_panel_driver);
+2 -14
drivers/video/omap/lcd_inn1610.c
··· 122 122 return 0; 123 123 } 124 124 125 - struct platform_driver innovator1610_panel_driver = { 125 + static struct platform_driver innovator1610_panel_driver = { 126 126 .probe = innovator1610_panel_probe, 127 127 .remove = innovator1610_panel_remove, 128 128 .suspend = innovator1610_panel_suspend, ··· 133 133 }, 134 134 }; 135 135 136 - static int __init innovator1610_panel_drv_init(void) 137 - { 138 - return platform_driver_register(&innovator1610_panel_driver); 139 - } 140 - 141 - static void __exit innovator1610_panel_drv_cleanup(void) 142 - { 143 - platform_driver_unregister(&innovator1610_panel_driver); 144 - } 145 - 146 - module_init(innovator1610_panel_drv_init); 147 - module_exit(innovator1610_panel_drv_cleanup); 148 - 136 + module_platform_driver(innovator1610_panel_driver);
-1
drivers/video/omap/lcd_mipid.c
··· 603 603 static struct spi_driver mipid_spi_driver = { 604 604 .driver = { 605 605 .name = MIPID_MODULE_NAME, 606 - .bus = &spi_bus_type, 607 606 .owner = THIS_MODULE, 608 607 }, 609 608 .probe = mipid_spi_probe,
+2 -14
drivers/video/omap/lcd_osk.c
··· 116 116 return 0; 117 117 } 118 118 119 - struct platform_driver osk_panel_driver = { 119 + static struct platform_driver osk_panel_driver = { 120 120 .probe = osk_panel_probe, 121 121 .remove = osk_panel_remove, 122 122 .suspend = osk_panel_suspend, ··· 127 127 }, 128 128 }; 129 129 130 - static int __init osk_panel_drv_init(void) 131 - { 132 - return platform_driver_register(&osk_panel_driver); 133 - } 134 - 135 - static void __exit osk_panel_drv_cleanup(void) 136 - { 137 - platform_driver_unregister(&osk_panel_driver); 138 - } 139 - 140 - module_init(osk_panel_drv_init); 141 - module_exit(osk_panel_drv_cleanup); 142 - 130 + module_platform_driver(osk_panel_driver);
+2 -14
drivers/video/omap/lcd_palmte.c
··· 97 97 return 0; 98 98 } 99 99 100 - struct platform_driver palmte_panel_driver = { 100 + static struct platform_driver palmte_panel_driver = { 101 101 .probe = palmte_panel_probe, 102 102 .remove = palmte_panel_remove, 103 103 .suspend = palmte_panel_suspend, ··· 108 108 }, 109 109 }; 110 110 111 - static int __init palmte_panel_drv_init(void) 112 - { 113 - return platform_driver_register(&palmte_panel_driver); 114 - } 115 - 116 - static void __exit palmte_panel_drv_cleanup(void) 117 - { 118 - platform_driver_unregister(&palmte_panel_driver); 119 - } 120 - 121 - module_init(palmte_panel_drv_init); 122 - module_exit(palmte_panel_drv_cleanup); 123 - 111 + module_platform_driver(palmte_panel_driver);
+2 -13
drivers/video/omap/lcd_palmtt.c
··· 102 102 return 0; 103 103 } 104 104 105 - struct platform_driver palmtt_panel_driver = { 105 + static struct platform_driver palmtt_panel_driver = { 106 106 .probe = palmtt_panel_probe, 107 107 .remove = palmtt_panel_remove, 108 108 .suspend = palmtt_panel_suspend, ··· 113 113 }, 114 114 }; 115 115 116 - static int __init palmtt_panel_drv_init(void) 117 - { 118 - return platform_driver_register(&palmtt_panel_driver); 119 - } 120 - 121 - static void __exit palmtt_panel_drv_cleanup(void) 122 - { 123 - platform_driver_unregister(&palmtt_panel_driver); 124 - } 125 - 126 - module_init(palmtt_panel_drv_init); 127 - module_exit(palmtt_panel_drv_cleanup); 116 + module_platform_driver(palmtt_panel_driver);
+2 -13
drivers/video/omap/lcd_palmz71.c
··· 98 98 return 0; 99 99 } 100 100 101 - struct platform_driver palmz71_panel_driver = { 101 + static struct platform_driver palmz71_panel_driver = { 102 102 .probe = palmz71_panel_probe, 103 103 .remove = palmz71_panel_remove, 104 104 .suspend = palmz71_panel_suspend, ··· 109 109 }, 110 110 }; 111 111 112 - static int __init palmz71_panel_drv_init(void) 113 - { 114 - return platform_driver_register(&palmz71_panel_driver); 115 - } 116 - 117 - static void __exit palmz71_panel_drv_cleanup(void) 118 - { 119 - platform_driver_unregister(&palmz71_panel_driver); 120 - } 121 - 122 - module_init(palmz71_panel_drv_init); 123 - module_exit(palmz71_panel_drv_cleanup); 112 + module_platform_driver(palmz71_panel_driver);
+1 -1
drivers/video/omap2/displays/Kconfig
··· 41 41 42 42 config PANEL_PICODLP 43 43 tristate "TI PICO DLP mini-projector" 44 - depends on OMAP2_DSS && I2C 44 + depends on OMAP2_DSS_DPI && I2C 45 45 help 46 46 A mini-projector used in TI's SDP4430 and EVM boards 47 47 For more info please visit http://www.dlp.com/projector/
-1
drivers/video/omap2/displays/panel-acx565akm.c
··· 803 803 static struct spi_driver acx565akm_spi_driver = { 804 804 .driver = { 805 805 .name = "acx565akm", 806 - .bus = &spi_bus_type, 807 806 .owner = THIS_MODULE, 808 807 }, 809 808 .probe = acx565akm_spi_probe,
+66
drivers/video/omap2/displays/panel-generic-dpi.c
··· 297 297 298 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 302 368 struct panel_drv_data {
-1
drivers/video/omap2/displays/panel-n8x0.c
··· 708 708 static struct spi_driver mipid_spi_driver = { 709 709 .driver = { 710 710 .name = "lcd_mipid", 711 - .bus = &spi_bus_type, 712 711 .owner = THIS_MODULE, 713 712 }, 714 713 .probe = mipid_spi_probe,
+52 -10
drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
··· 163 163 kfree(necd); 164 164 } 165 165 166 - static int nec_8048_panel_enable(struct omap_dss_device *dssdev) 166 + static int nec_8048_panel_power_on(struct omap_dss_device *dssdev) 167 167 { 168 - int r = 0; 168 + int r; 169 169 struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev); 170 170 struct backlight_device *bl = necd->bl; 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; 171 178 172 179 if (dssdev->platform_enable) { 173 180 r = dssdev->platform_enable(dssdev); 174 181 if (r) 175 - return r; 182 + goto err1; 176 183 } 177 184 178 185 r = nec_8048_bl_update_status(bl); 179 186 if (r < 0) 180 187 dev_err(&dssdev->dev, "failed to set lcd brightness\n"); 181 188 182 - r = omapdss_dpi_display_enable(dssdev); 183 - 189 + return 0; 190 + err1: 191 + omapdss_dpi_display_disable(dssdev); 192 + err0: 184 193 return r; 185 194 } 186 195 187 - static void nec_8048_panel_disable(struct omap_dss_device *dssdev) 196 + static void nec_8048_panel_power_off(struct omap_dss_device *dssdev) 188 197 { 189 198 struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev); 190 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 204 bl->props.brightness = 0; 195 205 nec_8048_bl_update_status(bl); 196 206 197 207 if (dssdev->platform_disable) 198 208 dssdev->platform_disable(dssdev); 209 + 210 + omapdss_dpi_display_disable(dssdev); 211 + } 212 + 213 + static 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 + 226 + static 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 201 233 static 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 239 return 0; 205 240 } 206 241 207 242 static 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 212 255 static int nec_8048_recommended_bpp(struct omap_dss_device *dssdev) ··· 346 303 .resume = nec_8048_spi_resume, 347 304 .driver = { 348 305 .name = "nec_8048_spi", 349 - .bus = &spi_bus_type, 350 306 .owner = THIS_MODULE, 351 307 }, 352 308 };
+14 -24
drivers/video/omap2/displays/panel-taal.c
··· 198 198 bool te_enabled; 199 199 200 200 atomic_t do_update; 201 - struct { 202 - u16 x; 203 - u16 y; 204 - u16 w; 205 - u16 h; 206 - } update_region; 207 201 int channel; 208 202 209 203 struct delayed_work te_timeout_work; ··· 1182 1188 if (r) 1183 1189 goto err; 1184 1190 1191 + r = dsi_enable_video_output(dssdev, td->channel); 1192 + if (r) 1193 + goto err; 1194 + 1185 1195 td->enabled = 1; 1186 1196 1187 1197 if (!td->intro_printed) { ··· 1214 1216 { 1215 1217 struct taal_data *td = dev_get_drvdata(&dssdev->dev); 1216 1218 int r; 1219 + 1220 + dsi_disable_video_output(dssdev, td->channel); 1217 1221 1218 1222 r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_OFF); 1219 1223 if (!r) ··· 1394 1394 if (old) { 1395 1395 cancel_delayed_work(&td->te_timeout_work); 1396 1396 1397 - r = omap_dsi_update(dssdev, td->channel, 1398 - td->update_region.x, 1399 - td->update_region.y, 1400 - td->update_region.w, 1401 - td->update_region.h, 1402 - taal_framedone_cb, dssdev); 1397 + r = omap_dsi_update(dssdev, td->channel, taal_framedone_cb, 1398 + dssdev); 1403 1399 if (r) 1404 1400 goto err; 1405 1401 } ··· 1440 1444 goto err; 1441 1445 } 1442 1446 1443 - r = omap_dsi_prepare_update(dssdev, &x, &y, &w, &h, true); 1444 - if (r) 1445 - goto err; 1446 - 1447 - r = taal_set_update_window(td, x, y, w, h); 1447 + /* XXX no need to send this every frame, but dsi break if not done */ 1448 + r = taal_set_update_window(td, 0, 0, 1449 + td->panel_config->timings.x_res, 1450 + td->panel_config->timings.y_res); 1448 1451 if (r) 1449 1452 goto err; 1450 1453 1451 1454 if (td->te_enabled && panel_data->use_ext_te) { 1452 - td->update_region.x = x; 1453 - td->update_region.y = y; 1454 - td->update_region.w = w; 1455 - td->update_region.h = h; 1456 - barrier(); 1457 1455 schedule_delayed_work(&td->te_timeout_work, 1458 1456 msecs_to_jiffies(250)); 1459 1457 atomic_set(&td->do_update, 1); 1460 1458 } else { 1461 - r = omap_dsi_update(dssdev, td->channel, x, y, w, h, 1462 - taal_framedone_cb, dssdev); 1459 + r = omap_dsi_update(dssdev, td->channel, taal_framedone_cb, 1460 + dssdev); 1463 1461 if (r) 1464 1462 goto err; 1465 1463 }
-1
drivers/video/omap2/displays/panel-tpo-td043mtea1.c
··· 512 512 static struct spi_driver tpo_td043_spi_driver = { 513 513 .driver = { 514 514 .name = "tpo_td043mtea1_panel_spi", 515 - .bus = &spi_bus_type, 516 515 .owner = THIS_MODULE, 517 516 }, 518 517 .probe = tpo_td043_spi_probe,
+2 -1
drivers/video/omap2/dss/Makefile
··· 1 1 obj-$(CONFIG_OMAP2_DSS) += omapdss.o 2 - omapdss-y := core.o dss.o dss_features.o dispc.o display.o manager.o overlay.o 2 + omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ 3 + manager.o overlay.o apply.o 3 4 omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o 4 5 omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o 5 6 omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
+1324
drivers/video/omap2/dss/apply.c
··· 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 + 59 + struct 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 + 83 + struct 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 + 104 + static 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 */ 112 + static spinlock_t data_lock; 113 + /* lock for blocking functions */ 114 + static DEFINE_MUTEX(apply_lock); 115 + static DECLARE_COMPLETION(extra_updated_completion); 116 + 117 + static void dss_register_vsync_isr(void); 118 + 119 + static struct ovl_priv_data *get_ovl_priv(struct omap_overlay *ovl) 120 + { 121 + return &dss_data.ovl_priv_data_array[ovl->id]; 122 + } 123 + 124 + static 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 + 129 + void 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 + 165 + static bool ovl_manual_update(struct omap_overlay *ovl) 166 + { 167 + return ovl->manager->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; 168 + } 169 + 170 + static bool mgr_manual_update(struct omap_overlay_manager *mgr) 171 + { 172 + return mgr->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; 173 + } 174 + 175 + static 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 + */ 212 + static 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 + */ 222 + static 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 + 228 + static 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 + 297 + static 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 */ 318 + static 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 */ 349 + static 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 + 376 + int 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 + 434 + int 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 + 497 + static 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 + 537 + static 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 + 561 + static 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 + 588 + static 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 + 615 + static 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 + 643 + void 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 + 672 + static void dss_apply_irq_handler(void *data, u32 mask); 673 + 674 + static 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 + 693 + static 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 + 712 + static 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 + 728 + static 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 + 776 + static 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 + 790 + static 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 + 804 + int 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 + 836 + static 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 + 849 + static 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 + 862 + static 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 + 900 + static 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 + 914 + static 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 + 926 + int 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 + 961 + out: 962 + mutex_unlock(&apply_lock); 963 + 964 + return 0; 965 + 966 + err: 967 + mp->enabled = false; 968 + spin_unlock_irqrestore(&data_lock, flags); 969 + mutex_unlock(&apply_lock); 970 + return r; 971 + } 972 + 973 + void 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 + 993 + out: 994 + mutex_unlock(&apply_lock); 995 + } 996 + 997 + int 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 + 1018 + void 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 + 1031 + int 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; 1058 + err: 1059 + mutex_unlock(&apply_lock); 1060 + return r; 1061 + } 1062 + 1063 + int 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; 1090 + err: 1091 + mutex_unlock(&apply_lock); 1092 + return r; 1093 + } 1094 + 1095 + 1096 + int 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 + 1117 + void 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 + 1130 + int 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; 1182 + err: 1183 + mutex_unlock(&apply_lock); 1184 + return r; 1185 + } 1186 + 1187 + int 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; 1220 + err: 1221 + mutex_unlock(&apply_lock); 1222 + return r; 1223 + } 1224 + 1225 + bool 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 + 1240 + int 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; 1282 + err2: 1283 + op->enabling = false; 1284 + spin_unlock_irqrestore(&data_lock, flags); 1285 + err1: 1286 + mutex_unlock(&apply_lock); 1287 + return r; 1288 + } 1289 + 1290 + int 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 + 1320 + err: 1321 + mutex_unlock(&apply_lock); 1322 + return r; 1323 + } 1324 +
+2
drivers/video/omap2/dss/core.c
··· 178 178 179 179 dss_features_init(); 180 180 181 + dss_apply_init(); 182 + 181 183 dss_init_overlay_managers(pdev); 182 184 dss_init_overlays(pdev); 183 185
+175 -230
drivers/video/omap2/dss/dispc.c
··· 64 64 u32 mask; 65 65 }; 66 66 67 - struct dispc_h_coef { 68 - s8 hc4; 69 - s8 hc3; 70 - u8 hc2; 71 - s8 hc1; 72 - s8 hc0; 73 - }; 74 - 75 - struct dispc_v_coef { 76 - s8 vc22; 77 - s8 vc2; 78 - u8 vc1; 79 - s8 vc0; 80 - s8 vc00; 81 - }; 82 - 83 67 enum omap_burst_size { 84 68 BURST_SIZE_X2 = 0, 85 69 BURST_SIZE_X4 = 1, ··· 422 438 return mgr ? mgr->device : NULL; 423 439 } 424 440 441 + u32 dispc_mgr_get_vsync_irq(enum omap_channel channel) 442 + { 443 + switch (channel) { 444 + case OMAP_DSS_CHANNEL_LCD: 445 + return DISPC_IRQ_VSYNC; 446 + case OMAP_DSS_CHANNEL_LCD2: 447 + return DISPC_IRQ_VSYNC2; 448 + case OMAP_DSS_CHANNEL_DIGIT: 449 + return DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; 450 + default: 451 + BUG(); 452 + } 453 + } 454 + 455 + u32 dispc_mgr_get_framedone_irq(enum omap_channel channel) 456 + { 457 + switch (channel) { 458 + case OMAP_DSS_CHANNEL_LCD: 459 + return DISPC_IRQ_FRAMEDONE; 460 + case OMAP_DSS_CHANNEL_LCD2: 461 + return DISPC_IRQ_FRAMEDONE2; 462 + case OMAP_DSS_CHANNEL_DIGIT: 463 + return 0; 464 + default: 465 + BUG(); 466 + } 467 + } 468 + 425 469 bool dispc_mgr_go_busy(enum omap_channel channel) 426 470 { 427 471 int bit; ··· 545 533 dispc_write_reg(DISPC_OVL_FIR_COEF_V2(plane, reg), value); 546 534 } 547 535 548 - static void dispc_ovl_set_scale_coef(enum omap_plane plane, int hscaleup, 549 - int vscaleup, int five_taps, 550 - enum omap_color_component color_comp) 536 + static void dispc_ovl_set_scale_coef(enum omap_plane plane, int fir_hinc, 537 + int fir_vinc, int five_taps, 538 + enum omap_color_component color_comp) 551 539 { 552 - /* Coefficients for horizontal up-sampling */ 553 - static const struct dispc_h_coef coef_hup[8] = { 554 - { 0, 0, 128, 0, 0 }, 555 - { -1, 13, 124, -8, 0 }, 556 - { -2, 30, 112, -11, -1 }, 557 - { -5, 51, 95, -11, -2 }, 558 - { 0, -9, 73, 73, -9 }, 559 - { -2, -11, 95, 51, -5 }, 560 - { -1, -11, 112, 30, -2 }, 561 - { 0, -8, 124, 13, -1 }, 562 - }; 563 - 564 - /* Coefficients for vertical up-sampling */ 565 - static const struct dispc_v_coef coef_vup_3tap[8] = { 566 - { 0, 0, 128, 0, 0 }, 567 - { 0, 3, 123, 2, 0 }, 568 - { 0, 12, 111, 5, 0 }, 569 - { 0, 32, 89, 7, 0 }, 570 - { 0, 0, 64, 64, 0 }, 571 - { 0, 7, 89, 32, 0 }, 572 - { 0, 5, 111, 12, 0 }, 573 - { 0, 2, 123, 3, 0 }, 574 - }; 575 - 576 - static const struct dispc_v_coef coef_vup_5tap[8] = { 577 - { 0, 0, 128, 0, 0 }, 578 - { -1, 13, 124, -8, 0 }, 579 - { -2, 30, 112, -11, -1 }, 580 - { -5, 51, 95, -11, -2 }, 581 - { 0, -9, 73, 73, -9 }, 582 - { -2, -11, 95, 51, -5 }, 583 - { -1, -11, 112, 30, -2 }, 584 - { 0, -8, 124, 13, -1 }, 585 - }; 586 - 587 - /* Coefficients for horizontal down-sampling */ 588 - static const struct dispc_h_coef coef_hdown[8] = { 589 - { 0, 36, 56, 36, 0 }, 590 - { 4, 40, 55, 31, -2 }, 591 - { 8, 44, 54, 27, -5 }, 592 - { 12, 48, 53, 22, -7 }, 593 - { -9, 17, 52, 51, 17 }, 594 - { -7, 22, 53, 48, 12 }, 595 - { -5, 27, 54, 44, 8 }, 596 - { -2, 31, 55, 40, 4 }, 597 - }; 598 - 599 - /* Coefficients for vertical down-sampling */ 600 - static const struct dispc_v_coef coef_vdown_3tap[8] = { 601 - { 0, 36, 56, 36, 0 }, 602 - { 0, 40, 57, 31, 0 }, 603 - { 0, 45, 56, 27, 0 }, 604 - { 0, 50, 55, 23, 0 }, 605 - { 0, 18, 55, 55, 0 }, 606 - { 0, 23, 55, 50, 0 }, 607 - { 0, 27, 56, 45, 0 }, 608 - { 0, 31, 57, 40, 0 }, 609 - }; 610 - 611 - static const struct dispc_v_coef coef_vdown_5tap[8] = { 612 - { 0, 36, 56, 36, 0 }, 613 - { 4, 40, 55, 31, -2 }, 614 - { 8, 44, 54, 27, -5 }, 615 - { 12, 48, 53, 22, -7 }, 616 - { -9, 17, 52, 51, 17 }, 617 - { -7, 22, 53, 48, 12 }, 618 - { -5, 27, 54, 44, 8 }, 619 - { -2, 31, 55, 40, 4 }, 620 - }; 621 - 622 - const struct dispc_h_coef *h_coef; 623 - const struct dispc_v_coef *v_coef; 540 + const struct dispc_coef *h_coef, *v_coef; 624 541 int i; 625 542 626 - if (hscaleup) 627 - h_coef = coef_hup; 628 - else 629 - h_coef = coef_hdown; 630 - 631 - if (vscaleup) 632 - v_coef = five_taps ? coef_vup_5tap : coef_vup_3tap; 633 - else 634 - v_coef = five_taps ? coef_vdown_5tap : coef_vdown_3tap; 543 + h_coef = dispc_ovl_get_scale_coef(fir_hinc, true); 544 + v_coef = dispc_ovl_get_scale_coef(fir_vinc, five_taps); 635 545 636 546 for (i = 0; i < 8; i++) { 637 547 u32 h, hv; 638 548 639 - h = FLD_VAL(h_coef[i].hc0, 7, 0) 640 - | FLD_VAL(h_coef[i].hc1, 15, 8) 641 - | FLD_VAL(h_coef[i].hc2, 23, 16) 642 - | FLD_VAL(h_coef[i].hc3, 31, 24); 643 - hv = FLD_VAL(h_coef[i].hc4, 7, 0) 644 - | FLD_VAL(v_coef[i].vc0, 15, 8) 645 - | FLD_VAL(v_coef[i].vc1, 23, 16) 646 - | FLD_VAL(v_coef[i].vc2, 31, 24); 549 + h = FLD_VAL(h_coef[i].hc0_vc00, 7, 0) 550 + | FLD_VAL(h_coef[i].hc1_vc0, 15, 8) 551 + | FLD_VAL(h_coef[i].hc2_vc1, 23, 16) 552 + | FLD_VAL(h_coef[i].hc3_vc2, 31, 24); 553 + hv = FLD_VAL(h_coef[i].hc4_vc22, 7, 0) 554 + | FLD_VAL(v_coef[i].hc1_vc0, 15, 8) 555 + | FLD_VAL(v_coef[i].hc2_vc1, 23, 16) 556 + | FLD_VAL(v_coef[i].hc3_vc2, 31, 24); 647 557 648 558 if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) { 649 559 dispc_ovl_write_firh_reg(plane, i, h); ··· 580 646 if (five_taps) { 581 647 for (i = 0; i < 8; i++) { 582 648 u32 v; 583 - v = FLD_VAL(v_coef[i].vc00, 7, 0) 584 - | FLD_VAL(v_coef[i].vc22, 15, 8); 649 + v = FLD_VAL(v_coef[i].hc0_vc00, 7, 0) 650 + | FLD_VAL(v_coef[i].hc4_vc22, 15, 8); 585 651 if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) 586 652 dispc_ovl_write_firv_reg(plane, i, v); 587 653 else ··· 809 875 REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1); 810 876 } 811 877 812 - static void dispc_ovl_set_channel_out(enum omap_plane plane, 813 - enum omap_channel channel) 878 + void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel) 814 879 { 815 880 int shift; 816 881 u32 val; ··· 856 923 dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); 857 924 } 858 925 926 + static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane) 927 + { 928 + int shift; 929 + u32 val; 930 + enum omap_channel channel; 931 + 932 + switch (plane) { 933 + case OMAP_DSS_GFX: 934 + shift = 8; 935 + break; 936 + case OMAP_DSS_VIDEO1: 937 + case OMAP_DSS_VIDEO2: 938 + case OMAP_DSS_VIDEO3: 939 + shift = 16; 940 + break; 941 + default: 942 + BUG(); 943 + } 944 + 945 + val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane)); 946 + 947 + if (dss_has_feature(FEAT_MGR_LCD2)) { 948 + if (FLD_GET(val, 31, 30) == 0) 949 + channel = FLD_GET(val, shift, shift); 950 + else 951 + channel = OMAP_DSS_CHANNEL_LCD2; 952 + } else { 953 + channel = FLD_GET(val, shift, shift); 954 + } 955 + 956 + return channel; 957 + } 958 + 859 959 static void dispc_ovl_set_burst_size(enum omap_plane plane, 860 960 enum omap_burst_size burst_size) 861 961 { ··· 930 964 REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9); 931 965 } 932 966 933 - void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable) 967 + static void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable) 934 968 { 935 969 u16 reg; 936 970 ··· 944 978 REG_FLD_MOD(reg, enable, 15, 15); 945 979 } 946 980 947 - void dispc_mgr_set_cpr_coef(enum omap_channel channel, 981 + static void dispc_mgr_set_cpr_coef(enum omap_channel channel, 948 982 struct omap_dss_cpr_coefs *coefs) 949 983 { 950 984 u32 coef_r, coef_g, coef_b; ··· 1023 1057 return dispc.fifo_size[plane]; 1024 1058 } 1025 1059 1026 - static void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, 1027 - u32 high) 1060 + void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high) 1028 1061 { 1029 1062 u8 hi_start, hi_end, lo_start, lo_end; 1030 1063 u32 unit; ··· 1134 1169 enum omap_color_component color_comp) 1135 1170 { 1136 1171 int fir_hinc, fir_vinc; 1137 - int hscaleup, vscaleup; 1138 - 1139 - hscaleup = orig_width <= out_width; 1140 - vscaleup = orig_height <= out_height; 1141 - 1142 - dispc_ovl_set_scale_coef(plane, hscaleup, vscaleup, five_taps, 1143 - color_comp); 1144 1172 1145 1173 fir_hinc = 1024 * orig_width / out_width; 1146 1174 fir_vinc = 1024 * orig_height / out_height; 1147 1175 1176 + dispc_ovl_set_scale_coef(plane, fir_hinc, fir_vinc, five_taps, 1177 + color_comp); 1148 1178 dispc_ovl_set_fir(plane, fir_hinc, fir_vinc, color_comp); 1149 1179 } 1150 1180 ··· 1614 1654 u32 fclk = 0; 1615 1655 u64 tmp, pclk = dispc_mgr_pclk_rate(channel); 1616 1656 1657 + if (height <= out_height && width <= out_width) 1658 + return (unsigned long) pclk; 1659 + 1617 1660 if (height > out_height) { 1618 1661 struct omap_dss_device *dssdev = dispc_mgr_get_device(channel); 1619 1662 unsigned int ppl = dssdev->panel.timings.x_res; ··· 1671 1708 else 1672 1709 vf = 1; 1673 1710 1674 - return dispc_mgr_pclk_rate(channel) * vf * hf; 1711 + if (cpu_is_omap24xx()) { 1712 + if (vf > 1 && hf > 1) 1713 + return dispc_mgr_pclk_rate(channel) * 4; 1714 + else 1715 + return dispc_mgr_pclk_rate(channel) * 2; 1716 + } else if (cpu_is_omap34xx()) { 1717 + return dispc_mgr_pclk_rate(channel) * vf * hf; 1718 + } else { 1719 + return dispc_mgr_pclk_rate(channel) * hf; 1720 + } 1675 1721 } 1676 1722 1677 1723 static int dispc_ovl_calc_scaling(enum omap_plane plane, ··· 1690 1718 { 1691 1719 struct omap_overlay *ovl = omap_dss_get_overlay(plane); 1692 1720 const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE); 1721 + const int maxsinglelinewidth = 1722 + dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH); 1693 1723 unsigned long fclk = 0; 1694 1724 1695 1725 if (width == out_width && height == out_height) ··· 1708 1734 out_height > height * 8) 1709 1735 return -EINVAL; 1710 1736 1711 - /* Must use 5-tap filter? */ 1712 - *five_taps = height > out_height * 2; 1713 - 1714 - if (!*five_taps) { 1737 + if (cpu_is_omap24xx()) { 1738 + if (width > maxsinglelinewidth) 1739 + DSSERR("Cannot scale max input width exceeded"); 1740 + *five_taps = false; 1741 + fclk = calc_fclk(channel, width, height, out_width, 1742 + out_height); 1743 + } else if (cpu_is_omap34xx()) { 1744 + if (width > (maxsinglelinewidth * 2)) { 1745 + DSSERR("Cannot setup scaling"); 1746 + DSSERR("width exceeds maximum width possible"); 1747 + return -EINVAL; 1748 + } 1749 + fclk = calc_fclk_five_taps(channel, width, height, out_width, 1750 + out_height, color_mode); 1751 + if (width > maxsinglelinewidth) { 1752 + if (height > out_height && height < out_height * 2) 1753 + *five_taps = false; 1754 + else { 1755 + DSSERR("cannot setup scaling with five taps"); 1756 + return -EINVAL; 1757 + } 1758 + } 1759 + if (!*five_taps) 1760 + fclk = calc_fclk(channel, width, height, out_width, 1761 + out_height); 1762 + } else { 1763 + if (width > maxsinglelinewidth) { 1764 + DSSERR("Cannot scale width exceeds max line width"); 1765 + return -EINVAL; 1766 + } 1715 1767 fclk = calc_fclk(channel, width, height, out_width, 1716 1768 out_height); 1717 - 1718 - /* Try 5-tap filter if 3-tap fclk is too high */ 1719 - if (cpu_is_omap34xx() && height > out_height && 1720 - fclk > dispc_fclk_rate()) 1721 - *five_taps = true; 1722 1769 } 1723 - 1724 - if (width > (2048 >> *five_taps)) { 1725 - DSSERR("failed to set up scaling, fclk too low\n"); 1726 - return -EINVAL; 1727 - } 1728 - 1729 - if (*five_taps) 1730 - fclk = calc_fclk_five_taps(channel, width, height, 1731 - out_width, out_height, color_mode); 1732 1770 1733 1771 DSSDBG("required fclk rate = %lu Hz\n", fclk); 1734 1772 DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate()); ··· 1757 1771 } 1758 1772 1759 1773 int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, 1760 - bool ilace, enum omap_channel channel, bool replication, 1761 - u32 fifo_low, u32 fifo_high) 1774 + bool ilace, bool replication) 1762 1775 { 1763 1776 struct omap_overlay *ovl = omap_dss_get_overlay(plane); 1764 - bool five_taps = false; 1777 + bool five_taps = true; 1765 1778 bool fieldmode = 0; 1766 1779 int r, cconv = 0; 1767 1780 unsigned offset0, offset1; ··· 1768 1783 s32 pix_inc; 1769 1784 u16 frame_height = oi->height; 1770 1785 unsigned int field_offset = 0; 1786 + u16 outw, outh; 1787 + enum omap_channel channel; 1788 + 1789 + channel = dispc_ovl_get_channel_out(plane); 1771 1790 1772 1791 DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> " 1773 - "%dx%d, cmode %x, rot %d, mir %d, ilace %d chan %d repl %d " 1774 - "fifo_low %d fifo high %d\n", plane, oi->paddr, oi->p_uv_addr, 1792 + "%dx%d, cmode %x, rot %d, mir %d, ilace %d chan %d repl %d\n", 1793 + plane, oi->paddr, oi->p_uv_addr, 1775 1794 oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height, 1776 1795 oi->out_width, oi->out_height, oi->color_mode, oi->rotation, 1777 - oi->mirror, ilace, channel, replication, fifo_low, fifo_high); 1796 + oi->mirror, ilace, channel, replication); 1778 1797 1779 1798 if (oi->paddr == 0) 1780 1799 return -EINVAL; 1781 1800 1782 - if (ilace && oi->height == oi->out_height) 1801 + outw = oi->out_width == 0 ? oi->width : oi->out_width; 1802 + outh = oi->out_height == 0 ? oi->height : oi->out_height; 1803 + 1804 + if (ilace && oi->height == outh) 1783 1805 fieldmode = 1; 1784 1806 1785 1807 if (ilace) { 1786 1808 if (fieldmode) 1787 1809 oi->height /= 2; 1788 1810 oi->pos_y /= 2; 1789 - oi->out_height /= 2; 1811 + outh /= 2; 1790 1812 1791 1813 DSSDBG("adjusting for ilace: height %d, pos_y %d, " 1792 1814 "out_height %d\n", 1793 - oi->height, oi->pos_y, oi->out_height); 1815 + oi->height, oi->pos_y, outh); 1794 1816 } 1795 1817 1796 1818 if (!dss_feat_color_mode_supported(plane, oi->color_mode)) 1797 1819 return -EINVAL; 1798 1820 1799 1821 r = dispc_ovl_calc_scaling(plane, channel, oi->width, oi->height, 1800 - oi->out_width, oi->out_height, oi->color_mode, 1822 + outw, outh, oi->color_mode, 1801 1823 &five_taps); 1802 1824 if (r) 1803 1825 return r; ··· 1822 1830 * so the integer part must be added to the base address of the 1823 1831 * bottom field. 1824 1832 */ 1825 - if (!oi->height || oi->height == oi->out_height) 1833 + if (!oi->height || oi->height == outh) 1826 1834 field_offset = 0; 1827 1835 else 1828 - field_offset = oi->height / oi->out_height / 2; 1836 + field_offset = oi->height / outh / 2; 1829 1837 } 1830 1838 1831 1839 /* Fields are independent but interleaved in memory. */ ··· 1861 1869 dispc_ovl_set_pix_inc(plane, pix_inc); 1862 1870 1863 1871 DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, oi->width, 1864 - oi->height, oi->out_width, oi->out_height); 1872 + oi->height, outw, outh); 1865 1873 1866 1874 dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y); 1867 1875 ··· 1869 1877 1870 1878 if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) { 1871 1879 dispc_ovl_set_scaling(plane, oi->width, oi->height, 1872 - oi->out_width, oi->out_height, 1880 + outw, outh, 1873 1881 ilace, five_taps, fieldmode, 1874 1882 oi->color_mode, oi->rotation); 1875 - dispc_ovl_set_vid_size(plane, oi->out_width, oi->out_height); 1883 + dispc_ovl_set_vid_size(plane, outw, outh); 1876 1884 dispc_ovl_set_vid_color_conv(plane, cconv); 1877 1885 } 1878 1886 ··· 1883 1891 dispc_ovl_set_pre_mult_alpha(plane, oi->pre_mult_alpha); 1884 1892 dispc_ovl_setup_global_alpha(plane, oi->global_alpha); 1885 1893 1886 - dispc_ovl_set_channel_out(plane, channel); 1887 - 1888 1894 dispc_ovl_enable_replication(plane, replication); 1889 - dispc_ovl_set_fifo_threshold(plane, fifo_low, fifo_high); 1890 1895 1891 1896 return 0; 1892 1897 } ··· 1905 1916 1906 1917 static void _enable_lcd_out(enum omap_channel channel, bool enable) 1907 1918 { 1908 - if (channel == OMAP_DSS_CHANNEL_LCD2) 1919 + if (channel == OMAP_DSS_CHANNEL_LCD2) { 1909 1920 REG_FLD_MOD(DISPC_CONTROL2, enable ? 1 : 0, 0, 0); 1910 - else 1921 + /* flush posted write */ 1922 + dispc_read_reg(DISPC_CONTROL2); 1923 + } else { 1911 1924 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0); 1925 + dispc_read_reg(DISPC_CONTROL); 1926 + } 1912 1927 } 1913 1928 1914 1929 static void dispc_mgr_enable_lcd_out(enum omap_channel channel, bool enable) ··· 1960 1967 static void _enable_digit_out(bool enable) 1961 1968 { 1962 1969 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1); 1970 + /* flush posted write */ 1971 + dispc_read_reg(DISPC_CONTROL); 1963 1972 } 1964 1973 1965 1974 static void dispc_mgr_enable_digit_out(bool enable) ··· 2119 2124 } 2120 2125 2121 2126 2122 - void dispc_mgr_set_default_color(enum omap_channel channel, u32 color) 2127 + static void dispc_mgr_set_default_color(enum omap_channel channel, u32 color) 2123 2128 { 2124 2129 dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color); 2125 2130 } 2126 2131 2127 - u32 dispc_mgr_get_default_color(enum omap_channel channel) 2128 - { 2129 - u32 l; 2130 - 2131 - BUG_ON(channel != OMAP_DSS_CHANNEL_DIGIT && 2132 - channel != OMAP_DSS_CHANNEL_LCD && 2133 - channel != OMAP_DSS_CHANNEL_LCD2); 2134 - 2135 - l = dispc_read_reg(DISPC_DEFAULT_COLOR(channel)); 2136 - 2137 - return l; 2138 - } 2139 - 2140 - void dispc_mgr_set_trans_key(enum omap_channel ch, 2132 + static void dispc_mgr_set_trans_key(enum omap_channel ch, 2141 2133 enum omap_dss_trans_key_type type, 2142 2134 u32 trans_key) 2143 2135 { ··· 2138 2156 dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key); 2139 2157 } 2140 2158 2141 - void dispc_mgr_get_trans_key(enum omap_channel ch, 2142 - enum omap_dss_trans_key_type *type, 2143 - u32 *trans_key) 2144 - { 2145 - if (type) { 2146 - if (ch == OMAP_DSS_CHANNEL_LCD) 2147 - *type = REG_GET(DISPC_CONFIG, 11, 11); 2148 - else if (ch == OMAP_DSS_CHANNEL_DIGIT) 2149 - *type = REG_GET(DISPC_CONFIG, 13, 13); 2150 - else if (ch == OMAP_DSS_CHANNEL_LCD2) 2151 - *type = REG_GET(DISPC_CONFIG2, 11, 11); 2152 - else 2153 - BUG(); 2154 - } 2155 - 2156 - if (trans_key) 2157 - *trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch)); 2158 - } 2159 - 2160 - void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable) 2159 + static void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable) 2161 2160 { 2162 2161 if (ch == OMAP_DSS_CHANNEL_LCD) 2163 2162 REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10); ··· 2148 2185 REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10); 2149 2186 } 2150 2187 2151 - void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable) 2188 + static void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, 2189 + bool enable) 2152 2190 { 2153 2191 if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) 2154 2192 return; ··· 2160 2196 REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19); 2161 2197 } 2162 2198 2163 - bool dispc_mgr_alpha_fixed_zorder_enabled(enum omap_channel ch) 2199 + void dispc_mgr_setup(enum omap_channel channel, 2200 + struct omap_overlay_manager_info *info) 2164 2201 { 2165 - bool enabled; 2166 - 2167 - if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) 2168 - return false; 2169 - 2170 - if (ch == OMAP_DSS_CHANNEL_LCD) 2171 - enabled = REG_GET(DISPC_CONFIG, 18, 18); 2172 - else if (ch == OMAP_DSS_CHANNEL_DIGIT) 2173 - enabled = REG_GET(DISPC_CONFIG, 19, 19); 2174 - else 2175 - BUG(); 2176 - 2177 - return enabled; 2202 + dispc_mgr_set_default_color(channel, info->default_color); 2203 + dispc_mgr_set_trans_key(channel, info->trans_key_type, info->trans_key); 2204 + dispc_mgr_enable_trans_key(channel, info->trans_enabled); 2205 + dispc_mgr_enable_alpha_fixed_zorder(channel, 2206 + info->partial_alpha_enabled); 2207 + if (dss_has_feature(FEAT_CPR)) { 2208 + dispc_mgr_enable_cpr(channel, info->cpr_enable); 2209 + dispc_mgr_set_cpr_coef(channel, &info->cpr_coefs); 2210 + } 2178 2211 } 2179 - 2180 - bool dispc_mgr_trans_key_enabled(enum omap_channel ch) 2181 - { 2182 - bool enabled; 2183 - 2184 - if (ch == OMAP_DSS_CHANNEL_LCD) 2185 - enabled = REG_GET(DISPC_CONFIG, 10, 10); 2186 - else if (ch == OMAP_DSS_CHANNEL_DIGIT) 2187 - enabled = REG_GET(DISPC_CONFIG, 12, 12); 2188 - else if (ch == OMAP_DSS_CHANNEL_LCD2) 2189 - enabled = REG_GET(DISPC_CONFIG2, 10, 10); 2190 - else 2191 - BUG(); 2192 - 2193 - return enabled; 2194 - } 2195 - 2196 2212 2197 2213 void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines) 2198 2214 { ··· 3128 3184 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { 3129 3185 struct omap_overlay_manager *mgr; 3130 3186 mgr = omap_dss_get_overlay_manager(i); 3131 - mgr->device->driver->disable(mgr->device); 3187 + if (mgr->device && mgr->device->driver) 3188 + mgr->device->driver->disable(mgr->device); 3132 3189 } 3133 3190 } 3134 3191
+11
drivers/video/omap2/dss/dispc.h
··· 97 97 #define DISPC_OVL_PRELOAD(n) (DISPC_OVL_BASE(n) + \ 98 98 DISPC_PRELOAD_OFFSET(n)) 99 99 100 + /* DISPC up/downsampling FIR filter coefficient structure */ 101 + struct dispc_coef { 102 + s8 hc4_vc22; 103 + s8 hc3_vc2; 104 + u8 hc2_vc1; 105 + s8 hc1_vc0; 106 + s8 hc0_vc00; 107 + }; 108 + 109 + const struct dispc_coef *dispc_ovl_get_scale_coef(int inc, int five_taps); 110 + 100 111 /* DISPC manager/channel specific registers */ 101 112 static inline u16 DISPC_DEFAULT_COLOR(enum omap_channel channel) 102 113 {
+326
drivers/video/omap2/dss/dispc_coefs.c
··· 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 + 26 + static 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 + 37 + static 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 + 48 + static 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 + 59 + static 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 + 70 + static 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 + 81 + static 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 + 92 + static 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 + 103 + static 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 + 114 + static 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 + 125 + static 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 + 136 + static 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 + 147 + static 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 + 158 + static 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 + 169 + static 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 + 180 + static 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 + 191 + static 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 + 202 + static 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 + 213 + static 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 + 224 + static 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 + 235 + static 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 + 246 + static 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 + 257 + static 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 + 268 + static 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 + 279 + static 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 + 290 + const 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 + }
+5 -2
drivers/video/omap2/dss/dpi.c
··· 223 223 224 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 230 return 0; 229 231 232 + err_mgr_enable: 230 233 err_set_mode: 231 234 if (dpi_use_dsi_pll(dssdev)) 232 235 dsi_pll_uninit(dpi.dsidev, true); ··· 252 249 253 250 void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) 254 251 { 255 - dssdev->manager->disable(dssdev->manager); 252 + dss_mgr_disable(dssdev->manager); 256 253 257 254 if (dpi_use_dsi_pll(dssdev)) { 258 255 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
+308 -294
drivers/video/omap2/dss/dsi.c
··· 203 203 typedef void (*omap_dsi_isr_t) (void *arg, u32 mask); 204 204 205 205 #define DSI_MAX_NR_ISRS 2 206 + #define DSI_MAX_NR_LANES 5 207 + 208 + enum 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 + 217 + struct dsi_lane_config { 218 + enum dsi_lane_function function; 219 + u8 polarity; 220 + }; 206 221 207 222 struct dsi_isr_data { 208 223 omap_dsi_isr_t isr; ··· 236 221 enum dsi_vc_source { 237 222 DSI_VC_SOURCE_L4 = 0, 238 223 DSI_VC_SOURCE_VP, 239 - }; 240 - 241 - enum dsi_lane { 242 - DSI_CLK_P = 1 << 0, 243 - DSI_CLK_N = 1 << 1, 244 - DSI_DATA1_P = 1 << 2, 245 - DSI_DATA1_N = 1 << 3, 246 - DSI_DATA2_P = 1 << 4, 247 - DSI_DATA2_N = 1 << 5, 248 - DSI_DATA3_P = 1 << 6, 249 - DSI_DATA3_N = 1 << 7, 250 - DSI_DATA4_P = 1 << 8, 251 - DSI_DATA4_N = 1 << 9, 252 - }; 253 - 254 - struct dsi_update_region { 255 - u16 x, y, w, h; 256 - struct omap_dss_device *device; 257 224 }; 258 225 259 226 struct dsi_irq_stats { ··· 287 290 struct dsi_isr_tables isr_tables_copy; 288 291 289 292 int update_channel; 290 - struct dsi_update_region update_region; 293 + #ifdef DEBUG 294 + unsigned update_bytes; 295 + #endif 291 296 292 297 bool te_enabled; 293 298 bool ulps_enabled; ··· 326 327 unsigned long fint_min, fint_max; 327 328 unsigned long lpdiv_max; 328 329 329 - int num_data_lanes; 330 + unsigned num_lanes_supported; 331 + 332 + struct dsi_lane_config lanes[DSI_MAX_NR_LANES]; 333 + unsigned num_lanes_used; 330 334 331 335 unsigned scp_clk_refcount; 332 336 }; ··· 415 413 static inline int wait_for_bit_change(struct platform_device *dsidev, 416 414 const struct dsi_reg idx, int bitnum, int value) 417 415 { 418 - int t = 100000; 416 + unsigned long timeout; 417 + ktime_t wait; 418 + int t; 419 419 420 - while (REG_GET(dsidev, idx, bitnum, bitnum) != value) { 421 - if (--t == 0) 422 - return !value; 420 + /* first busyloop to see if the bit changes right away */ 421 + t = 100; 422 + while (t-- > 0) { 423 + if (REG_GET(dsidev, idx, bitnum, bitnum) == value) 424 + return value; 423 425 } 424 426 425 - return value; 427 + /* then loop for 500ms, sleeping for 1ms in between */ 428 + timeout = jiffies + msecs_to_jiffies(500); 429 + while (time_before(jiffies, timeout)) { 430 + if (REG_GET(dsidev, idx, bitnum, bitnum) == value) 431 + return value; 432 + 433 + wait = ns_to_ktime(1000 * 1000); 434 + set_current_state(TASK_UNINTERRUPTIBLE); 435 + schedule_hrtimeout(&wait, HRTIMER_MODE_REL); 436 + } 437 + 438 + return !value; 426 439 } 427 440 428 441 u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt) ··· 471 454 static void dsi_perf_show(struct platform_device *dsidev, const char *name) 472 455 { 473 456 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 474 - struct omap_dss_device *dssdev = dsi->update_region.device; 475 457 ktime_t t, setup_time, trans_time; 476 458 u32 total_bytes; 477 459 u32 setup_us, trans_us, total_us; ··· 492 476 493 477 total_us = setup_us + trans_us; 494 478 495 - total_bytes = dsi->update_region.w * 496 - dsi->update_region.h * 497 - dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8; 479 + total_bytes = dsi->update_bytes; 498 480 499 481 printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), " 500 482 "%u bytes, %u kbytes/sec\n", ··· 1734 1720 seq_printf(s, "CLKIN4DDR\t%-16luregm %u\n", 1735 1721 cinfo->clkin4ddr, cinfo->regm); 1736 1722 1737 - seq_printf(s, "%s (%s)\t%-16luregm_dispc %u\t(%s)\n", 1738 - dss_get_generic_clk_source_name(dispc_clk_src), 1739 - dss_feat_get_clk_source_name(dispc_clk_src), 1723 + seq_printf(s, "DSI_PLL_HSDIV_DISPC (%s)\t%-16luregm_dispc %u\t(%s)\n", 1724 + dss_feat_get_clk_source_name(dsi_module == 0 ? 1725 + OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC : 1726 + OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC), 1740 1727 cinfo->dsi_pll_hsdiv_dispc_clk, 1741 1728 cinfo->regm_dispc, 1742 1729 dispc_clk_src == OMAP_DSS_CLK_SRC_FCK ? 1743 1730 "off" : "on"); 1744 1731 1745 - seq_printf(s, "%s (%s)\t%-16luregm_dsi %u\t(%s)\n", 1746 - dss_get_generic_clk_source_name(dsi_clk_src), 1747 - dss_feat_get_clk_source_name(dsi_clk_src), 1732 + seq_printf(s, "DSI_PLL_HSDIV_DSI (%s)\t%-16luregm_dsi %u\t(%s)\n", 1733 + dss_feat_get_clk_source_name(dsi_module == 0 ? 1734 + OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI : 1735 + OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI), 1748 1736 cinfo->dsi_pll_hsdiv_dsi_clk, 1749 1737 cinfo->regm_dsi, 1750 1738 dsi_clk_src == OMAP_DSS_CLK_SRC_FCK ? ··· 2045 2029 return 0; 2046 2030 } 2047 2031 2048 - /* Number of data lanes present on DSI interface */ 2049 - static inline int dsi_get_num_data_lanes(struct platform_device *dsidev) 2050 - { 2051 - /* DSI on OMAP3 doesn't have register DSI_GNQ, set number 2052 - * of data lanes as 2 by default */ 2053 - if (dss_has_feature(FEAT_DSI_GNQ)) 2054 - return REG_GET(dsidev, DSI_GNQ, 11, 9); /* NB_DATA_LANES */ 2055 - else 2056 - return 2; 2057 - } 2058 - 2059 - /* Number of data lanes used by the dss device */ 2060 - static inline int dsi_get_num_data_lanes_dssdev(struct omap_dss_device *dssdev) 2061 - { 2062 - int num_data_lanes = 0; 2063 - 2064 - if (dssdev->phy.dsi.data1_lane != 0) 2065 - num_data_lanes++; 2066 - if (dssdev->phy.dsi.data2_lane != 0) 2067 - num_data_lanes++; 2068 - if (dssdev->phy.dsi.data3_lane != 0) 2069 - num_data_lanes++; 2070 - if (dssdev->phy.dsi.data4_lane != 0) 2071 - num_data_lanes++; 2072 - 2073 - return num_data_lanes; 2074 - } 2075 - 2076 2032 static unsigned dsi_get_line_buf_size(struct platform_device *dsidev) 2077 2033 { 2078 2034 int val; ··· 2076 2088 } 2077 2089 } 2078 2090 2079 - static void dsi_set_lane_config(struct omap_dss_device *dssdev) 2091 + static int dsi_parse_lane_config(struct omap_dss_device *dssdev) 2080 2092 { 2081 2093 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 2082 - u32 r; 2083 - int num_data_lanes_dssdev = dsi_get_num_data_lanes_dssdev(dssdev); 2094 + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2095 + u8 lanes[DSI_MAX_NR_LANES]; 2096 + u8 polarities[DSI_MAX_NR_LANES]; 2097 + int num_lanes, i; 2084 2098 2085 - int clk_lane = dssdev->phy.dsi.clk_lane; 2086 - int data1_lane = dssdev->phy.dsi.data1_lane; 2087 - int data2_lane = dssdev->phy.dsi.data2_lane; 2088 - int clk_pol = dssdev->phy.dsi.clk_pol; 2089 - int data1_pol = dssdev->phy.dsi.data1_pol; 2090 - int data2_pol = dssdev->phy.dsi.data2_pol; 2099 + static const enum dsi_lane_function functions[] = { 2100 + DSI_LANE_CLK, 2101 + DSI_LANE_DATA1, 2102 + DSI_LANE_DATA2, 2103 + DSI_LANE_DATA3, 2104 + DSI_LANE_DATA4, 2105 + }; 2106 + 2107 + lanes[0] = dssdev->phy.dsi.clk_lane; 2108 + lanes[1] = dssdev->phy.dsi.data1_lane; 2109 + lanes[2] = dssdev->phy.dsi.data2_lane; 2110 + lanes[3] = dssdev->phy.dsi.data3_lane; 2111 + lanes[4] = dssdev->phy.dsi.data4_lane; 2112 + polarities[0] = dssdev->phy.dsi.clk_pol; 2113 + polarities[1] = dssdev->phy.dsi.data1_pol; 2114 + polarities[2] = dssdev->phy.dsi.data2_pol; 2115 + polarities[3] = dssdev->phy.dsi.data3_pol; 2116 + polarities[4] = dssdev->phy.dsi.data4_pol; 2117 + 2118 + num_lanes = 0; 2119 + 2120 + for (i = 0; i < dsi->num_lanes_supported; ++i) 2121 + dsi->lanes[i].function = DSI_LANE_UNUSED; 2122 + 2123 + for (i = 0; i < dsi->num_lanes_supported; ++i) { 2124 + int num; 2125 + 2126 + if (lanes[i] == DSI_LANE_UNUSED) 2127 + break; 2128 + 2129 + num = lanes[i] - 1; 2130 + 2131 + if (num >= dsi->num_lanes_supported) 2132 + return -EINVAL; 2133 + 2134 + if (dsi->lanes[num].function != DSI_LANE_UNUSED) 2135 + return -EINVAL; 2136 + 2137 + dsi->lanes[num].function = functions[i]; 2138 + dsi->lanes[num].polarity = polarities[i]; 2139 + num_lanes++; 2140 + } 2141 + 2142 + if (num_lanes < 2 || num_lanes > dsi->num_lanes_supported) 2143 + return -EINVAL; 2144 + 2145 + dsi->num_lanes_used = num_lanes; 2146 + 2147 + return 0; 2148 + } 2149 + 2150 + static int dsi_set_lane_config(struct omap_dss_device *dssdev) 2151 + { 2152 + struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 2153 + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2154 + static const u8 offsets[] = { 0, 4, 8, 12, 16 }; 2155 + static const enum dsi_lane_function functions[] = { 2156 + DSI_LANE_CLK, 2157 + DSI_LANE_DATA1, 2158 + DSI_LANE_DATA2, 2159 + DSI_LANE_DATA3, 2160 + DSI_LANE_DATA4, 2161 + }; 2162 + u32 r; 2163 + int i; 2091 2164 2092 2165 r = dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1); 2093 - r = FLD_MOD(r, clk_lane, 2, 0); 2094 - r = FLD_MOD(r, clk_pol, 3, 3); 2095 - r = FLD_MOD(r, data1_lane, 6, 4); 2096 - r = FLD_MOD(r, data1_pol, 7, 7); 2097 - r = FLD_MOD(r, data2_lane, 10, 8); 2098 - r = FLD_MOD(r, data2_pol, 11, 11); 2099 - if (num_data_lanes_dssdev > 2) { 2100 - int data3_lane = dssdev->phy.dsi.data3_lane; 2101 - int data3_pol = dssdev->phy.dsi.data3_pol; 2102 2166 2103 - r = FLD_MOD(r, data3_lane, 14, 12); 2104 - r = FLD_MOD(r, data3_pol, 15, 15); 2105 - } 2106 - if (num_data_lanes_dssdev > 3) { 2107 - int data4_lane = dssdev->phy.dsi.data4_lane; 2108 - int data4_pol = dssdev->phy.dsi.data4_pol; 2167 + for (i = 0; i < dsi->num_lanes_used; ++i) { 2168 + unsigned offset = offsets[i]; 2169 + unsigned polarity, lane_number; 2170 + unsigned t; 2109 2171 2110 - r = FLD_MOD(r, data4_lane, 18, 16); 2111 - r = FLD_MOD(r, data4_pol, 19, 19); 2172 + for (t = 0; t < dsi->num_lanes_supported; ++t) 2173 + if (dsi->lanes[t].function == functions[i]) 2174 + break; 2175 + 2176 + if (t == dsi->num_lanes_supported) 2177 + return -EINVAL; 2178 + 2179 + lane_number = t; 2180 + polarity = dsi->lanes[t].polarity; 2181 + 2182 + r = FLD_MOD(r, lane_number + 1, offset + 2, offset); 2183 + r = FLD_MOD(r, polarity, offset + 3, offset + 3); 2112 2184 } 2185 + 2186 + /* clear the unused lanes */ 2187 + for (; i < dsi->num_lanes_supported; ++i) { 2188 + unsigned offset = offsets[i]; 2189 + 2190 + r = FLD_MOD(r, 0, offset + 2, offset); 2191 + r = FLD_MOD(r, 0, offset + 3, offset + 3); 2192 + } 2193 + 2113 2194 dsi_write_reg(dsidev, DSI_COMPLEXIO_CFG1, r); 2114 2195 2115 - /* The configuration of the DSI complex I/O (number of data lanes, 2116 - position, differential order) should not be changed while 2117 - DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. In order for 2118 - the hardware to take into account a new configuration of the complex 2119 - I/O (done in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to 2120 - follow this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1, 2121 - then reset the DSS.DSI_CTRL[0] IF_EN to 0, then set 2122 - DSS.DSI_CLK_CTRL[20] LP_CLK_ENABLE to 1 and finally set again the 2123 - DSS.DSI_CTRL[0] IF_EN bit to 1. If the sequence is not followed, the 2124 - DSI complex I/O configuration is unknown. */ 2125 - 2126 - /* 2127 - REG_FLD_MOD(dsidev, DSI_CTRL, 1, 0, 0); 2128 - REG_FLD_MOD(dsidev, DSI_CTRL, 0, 0, 0); 2129 - REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20); 2130 - REG_FLD_MOD(dsidev, DSI_CTRL, 1, 0, 0); 2131 - */ 2196 + return 0; 2132 2197 } 2133 2198 2134 2199 static inline unsigned ns2ddr(struct platform_device *dsidev, unsigned ns) ··· 2271 2230 dsi_write_reg(dsidev, DSI_DSIPHY_CFG2, r); 2272 2231 } 2273 2232 2233 + /* lane masks have lane 0 at lsb. mask_p for positive lines, n for negative */ 2274 2234 static void dsi_cio_enable_lane_override(struct omap_dss_device *dssdev, 2275 - enum dsi_lane lanes) 2235 + unsigned mask_p, unsigned mask_n) 2276 2236 { 2277 2237 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 2278 2238 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2279 - int clk_lane = dssdev->phy.dsi.clk_lane; 2280 - int data1_lane = dssdev->phy.dsi.data1_lane; 2281 - int data2_lane = dssdev->phy.dsi.data2_lane; 2282 - int data3_lane = dssdev->phy.dsi.data3_lane; 2283 - int data4_lane = dssdev->phy.dsi.data4_lane; 2284 - int clk_pol = dssdev->phy.dsi.clk_pol; 2285 - int data1_pol = dssdev->phy.dsi.data1_pol; 2286 - int data2_pol = dssdev->phy.dsi.data2_pol; 2287 - int data3_pol = dssdev->phy.dsi.data3_pol; 2288 - int data4_pol = dssdev->phy.dsi.data4_pol; 2239 + int i; 2240 + u32 l; 2241 + u8 lptxscp_start = dsi->num_lanes_supported == 3 ? 22 : 26; 2289 2242 2290 - u32 l = 0; 2291 - u8 lptxscp_start = dsi->num_data_lanes == 2 ? 22 : 26; 2243 + l = 0; 2292 2244 2293 - if (lanes & DSI_CLK_P) 2294 - l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 0 : 1)); 2295 - if (lanes & DSI_CLK_N) 2296 - l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 1 : 0)); 2245 + for (i = 0; i < dsi->num_lanes_supported; ++i) { 2246 + unsigned p = dsi->lanes[i].polarity; 2297 2247 2298 - if (lanes & DSI_DATA1_P) 2299 - l |= 1 << ((data1_lane - 1) * 2 + (data1_pol ? 0 : 1)); 2300 - if (lanes & DSI_DATA1_N) 2301 - l |= 1 << ((data1_lane - 1) * 2 + (data1_pol ? 1 : 0)); 2248 + if (mask_p & (1 << i)) 2249 + l |= 1 << (i * 2 + (p ? 0 : 1)); 2302 2250 2303 - if (lanes & DSI_DATA2_P) 2304 - l |= 1 << ((data2_lane - 1) * 2 + (data2_pol ? 0 : 1)); 2305 - if (lanes & DSI_DATA2_N) 2306 - l |= 1 << ((data2_lane - 1) * 2 + (data2_pol ? 1 : 0)); 2251 + if (mask_n & (1 << i)) 2252 + l |= 1 << (i * 2 + (p ? 1 : 0)); 2253 + } 2307 2254 2308 - if (lanes & DSI_DATA3_P) 2309 - l |= 1 << ((data3_lane - 1) * 2 + (data3_pol ? 0 : 1)); 2310 - if (lanes & DSI_DATA3_N) 2311 - l |= 1 << ((data3_lane - 1) * 2 + (data3_pol ? 1 : 0)); 2312 - 2313 - if (lanes & DSI_DATA4_P) 2314 - l |= 1 << ((data4_lane - 1) * 2 + (data4_pol ? 0 : 1)); 2315 - if (lanes & DSI_DATA4_N) 2316 - l |= 1 << ((data4_lane - 1) * 2 + (data4_pol ? 1 : 0)); 2317 2255 /* 2318 2256 * Bits in REGLPTXSCPDAT4TO0DXDY: 2319 2257 * 17: DY0 18: DX0 ··· 2325 2305 static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev) 2326 2306 { 2327 2307 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 2328 - int t; 2329 - int bits[3]; 2330 - bool in_use[3]; 2308 + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2309 + int t, i; 2310 + bool in_use[DSI_MAX_NR_LANES]; 2311 + static const u8 offsets_old[] = { 28, 27, 26 }; 2312 + static const u8 offsets_new[] = { 24, 25, 26, 27, 28 }; 2313 + const u8 *offsets; 2331 2314 2332 - if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) { 2333 - bits[0] = 28; 2334 - bits[1] = 27; 2335 - bits[2] = 26; 2336 - } else { 2337 - bits[0] = 24; 2338 - bits[1] = 25; 2339 - bits[2] = 26; 2340 - } 2315 + if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) 2316 + offsets = offsets_old; 2317 + else 2318 + offsets = offsets_new; 2341 2319 2342 - in_use[0] = false; 2343 - in_use[1] = false; 2344 - in_use[2] = false; 2345 - 2346 - if (dssdev->phy.dsi.clk_lane != 0) 2347 - in_use[dssdev->phy.dsi.clk_lane - 1] = true; 2348 - if (dssdev->phy.dsi.data1_lane != 0) 2349 - in_use[dssdev->phy.dsi.data1_lane - 1] = true; 2350 - if (dssdev->phy.dsi.data2_lane != 0) 2351 - in_use[dssdev->phy.dsi.data2_lane - 1] = true; 2320 + for (i = 0; i < dsi->num_lanes_supported; ++i) 2321 + in_use[i] = dsi->lanes[i].function != DSI_LANE_UNUSED; 2352 2322 2353 2323 t = 100000; 2354 2324 while (true) { 2355 2325 u32 l; 2356 - int i; 2357 2326 int ok; 2358 2327 2359 2328 l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5); 2360 2329 2361 2330 ok = 0; 2362 - for (i = 0; i < 3; ++i) { 2363 - if (!in_use[i] || (l & (1 << bits[i]))) 2331 + for (i = 0; i < dsi->num_lanes_supported; ++i) { 2332 + if (!in_use[i] || (l & (1 << offsets[i]))) 2364 2333 ok++; 2365 2334 } 2366 2335 2367 - if (ok == 3) 2336 + if (ok == dsi->num_lanes_supported) 2368 2337 break; 2369 2338 2370 2339 if (--t == 0) { 2371 - for (i = 0; i < 3; ++i) { 2372 - if (!in_use[i] || (l & (1 << bits[i]))) 2340 + for (i = 0; i < dsi->num_lanes_supported; ++i) { 2341 + if (!in_use[i] || (l & (1 << offsets[i]))) 2373 2342 continue; 2374 2343 2375 2344 DSSERR("CIO TXCLKESC%d domain not coming " \ ··· 2371 2362 return 0; 2372 2363 } 2373 2364 2365 + /* return bitmask of enabled lanes, lane0 being the lsb */ 2374 2366 static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev) 2375 2367 { 2376 - unsigned lanes = 0; 2368 + struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 2369 + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2370 + unsigned mask = 0; 2371 + int i; 2377 2372 2378 - if (dssdev->phy.dsi.clk_lane != 0) 2379 - lanes |= 1 << (dssdev->phy.dsi.clk_lane - 1); 2380 - if (dssdev->phy.dsi.data1_lane != 0) 2381 - lanes |= 1 << (dssdev->phy.dsi.data1_lane - 1); 2382 - if (dssdev->phy.dsi.data2_lane != 0) 2383 - lanes |= 1 << (dssdev->phy.dsi.data2_lane - 1); 2384 - if (dssdev->phy.dsi.data3_lane != 0) 2385 - lanes |= 1 << (dssdev->phy.dsi.data3_lane - 1); 2386 - if (dssdev->phy.dsi.data4_lane != 0) 2387 - lanes |= 1 << (dssdev->phy.dsi.data4_lane - 1); 2373 + for (i = 0; i < dsi->num_lanes_supported; ++i) { 2374 + if (dsi->lanes[i].function != DSI_LANE_UNUSED) 2375 + mask |= 1 << i; 2376 + } 2388 2377 2389 - return lanes; 2378 + return mask; 2390 2379 } 2391 2380 2392 2381 static int dsi_cio_init(struct omap_dss_device *dssdev) ··· 2392 2385 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 2393 2386 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 2394 2387 int r; 2395 - int num_data_lanes_dssdev = dsi_get_num_data_lanes_dssdev(dssdev); 2396 2388 u32 l; 2397 2389 2398 2390 DSSDBGF(); ··· 2413 2407 goto err_scp_clk_dom; 2414 2408 } 2415 2409 2416 - dsi_set_lane_config(dssdev); 2410 + r = dsi_set_lane_config(dssdev); 2411 + if (r) 2412 + goto err_scp_clk_dom; 2417 2413 2418 2414 /* set TX STOP MODE timer to maximum for this operation */ 2419 2415 l = dsi_read_reg(dsidev, DSI_TIMING1); ··· 2426 2418 dsi_write_reg(dsidev, DSI_TIMING1, l); 2427 2419 2428 2420 if (dsi->ulps_enabled) { 2429 - u32 lane_mask = DSI_CLK_P | DSI_DATA1_P | DSI_DATA2_P; 2421 + unsigned mask_p; 2422 + int i; 2430 2423 2431 2424 DSSDBG("manual ulps exit\n"); 2432 2425 ··· 2436 2427 * ULPS exit sequence, as after reset the DSS HW thinks 2437 2428 * that we are not in ULPS mode, and refuses to send the 2438 2429 * sequence. So we need to send the ULPS exit sequence 2439 - * manually. 2430 + * manually by setting positive lines high and negative lines 2431 + * low for 1ms. 2440 2432 */ 2441 2433 2442 - if (num_data_lanes_dssdev > 2) 2443 - lane_mask |= DSI_DATA3_P; 2434 + mask_p = 0; 2444 2435 2445 - if (num_data_lanes_dssdev > 3) 2446 - lane_mask |= DSI_DATA4_P; 2436 + for (i = 0; i < dsi->num_lanes_supported; ++i) { 2437 + if (dsi->lanes[i].function == DSI_LANE_UNUSED) 2438 + continue; 2439 + mask_p |= 1 << i; 2440 + } 2447 2441 2448 - dsi_cio_enable_lane_override(dssdev, lane_mask); 2442 + dsi_cio_enable_lane_override(dssdev, mask_p, 0); 2449 2443 } 2450 2444 2451 2445 r = dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ON); ··· 2924 2912 } 2925 2913 2926 2914 REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */ 2915 + 2916 + /* flush posted write */ 2917 + dsi_read_reg(dsidev, DSI_VC_CTRL(channel)); 2927 2918 2928 2919 return 0; 2929 2920 } ··· 3528 3513 { 3529 3514 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 3530 3515 DECLARE_COMPLETION_ONSTACK(completion); 3531 - int r; 3516 + int r, i; 3517 + unsigned mask; 3532 3518 3533 3519 DSSDBGF(); 3534 3520 ··· 3540 3524 if (dsi->ulps_enabled) 3541 3525 return 0; 3542 3526 3527 + /* DDR_CLK_ALWAYS_ON */ 3543 3528 if (REG_GET(dsidev, DSI_CLK_CTRL, 13, 13)) { 3544 - DSSERR("DDR_CLK_ALWAYS_ON enabled when entering ULPS\n"); 3545 - return -EIO; 3529 + dsi_if_enable(dsidev, 0); 3530 + REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 13, 13); 3531 + dsi_if_enable(dsidev, 1); 3546 3532 } 3547 3533 3548 3534 dsi_sync_vc(dsidev, 0); ··· 3574 3556 if (r) 3575 3557 return r; 3576 3558 3559 + mask = 0; 3560 + 3561 + for (i = 0; i < dsi->num_lanes_supported; ++i) { 3562 + if (dsi->lanes[i].function == DSI_LANE_UNUSED) 3563 + continue; 3564 + mask |= 1 << i; 3565 + } 3577 3566 /* Assert TxRequestEsc for data lanes and TxUlpsClk for clk lane */ 3578 3567 /* LANEx_ULPS_SIG2 */ 3579 - REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (1 << 0) | (1 << 1) | (1 << 2), 3580 - 7, 5); 3568 + REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, mask, 9, 5); 3569 + 3570 + /* flush posted write and wait for SCP interface to finish the write */ 3571 + dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG2); 3581 3572 3582 3573 if (wait_for_completion_timeout(&completion, 3583 3574 msecs_to_jiffies(1000)) == 0) { ··· 3599 3572 DSI_CIO_IRQ_ULPSACTIVENOT_ALL0); 3600 3573 3601 3574 /* Reset LANEx_ULPS_SIG2 */ 3602 - REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (0 << 0) | (0 << 1) | (0 << 2), 3603 - 7, 5); 3575 + REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, 0, 9, 5); 3576 + 3577 + /* flush posted write and wait for SCP interface to finish the write */ 3578 + dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG2); 3604 3579 3605 3580 dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ULPS); 3606 3581 ··· 3865 3836 static void dsi_proto_timings(struct omap_dss_device *dssdev) 3866 3837 { 3867 3838 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3839 + struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 3868 3840 unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail; 3869 3841 unsigned tclk_pre, tclk_post; 3870 3842 unsigned ths_prepare, ths_prepare_ths_zero, ths_zero; ··· 3873 3843 unsigned ddr_clk_pre, ddr_clk_post; 3874 3844 unsigned enter_hs_mode_lat, exit_hs_mode_lat; 3875 3845 unsigned ths_eot; 3876 - int ndl = dsi_get_num_data_lanes_dssdev(dssdev); 3846 + int ndl = dsi->num_lanes_used - 1; 3877 3847 u32 r; 3878 3848 3879 3849 r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0); ··· 3975 3945 } 3976 3946 } 3977 3947 3978 - int dsi_video_mode_enable(struct omap_dss_device *dssdev, int channel) 3948 + int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) 3979 3949 { 3980 3950 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 3981 3951 int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); 3982 3952 u8 data_type; 3983 3953 u16 word_count; 3954 + int r; 3984 3955 3985 - switch (dssdev->panel.dsi_pix_fmt) { 3986 - case OMAP_DSS_DSI_FMT_RGB888: 3987 - data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24; 3988 - break; 3989 - case OMAP_DSS_DSI_FMT_RGB666: 3990 - data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18; 3991 - break; 3992 - case OMAP_DSS_DSI_FMT_RGB666_PACKED: 3993 - data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18; 3994 - break; 3995 - case OMAP_DSS_DSI_FMT_RGB565: 3996 - data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16; 3997 - break; 3998 - default: 3999 - BUG(); 4000 - }; 3956 + if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { 3957 + switch (dssdev->panel.dsi_pix_fmt) { 3958 + case OMAP_DSS_DSI_FMT_RGB888: 3959 + data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24; 3960 + break; 3961 + case OMAP_DSS_DSI_FMT_RGB666: 3962 + data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18; 3963 + break; 3964 + case OMAP_DSS_DSI_FMT_RGB666_PACKED: 3965 + data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18; 3966 + break; 3967 + case OMAP_DSS_DSI_FMT_RGB565: 3968 + data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16; 3969 + break; 3970 + default: 3971 + BUG(); 3972 + }; 4001 3973 4002 - dsi_if_enable(dsidev, false); 4003 - dsi_vc_enable(dsidev, channel, false); 3974 + dsi_if_enable(dsidev, false); 3975 + dsi_vc_enable(dsidev, channel, false); 4004 3976 4005 - /* MODE, 1 = video mode */ 4006 - REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4); 3977 + /* MODE, 1 = video mode */ 3978 + REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4); 4007 3979 4008 - word_count = DIV_ROUND_UP(dssdev->panel.timings.x_res * bpp, 8); 3980 + word_count = DIV_ROUND_UP(dssdev->panel.timings.x_res * bpp, 8); 4009 3981 4010 - dsi_vc_write_long_header(dsidev, channel, data_type, word_count, 0); 3982 + dsi_vc_write_long_header(dsidev, channel, data_type, 3983 + word_count, 0); 4011 3984 4012 - dsi_vc_enable(dsidev, channel, true); 4013 - dsi_if_enable(dsidev, true); 3985 + dsi_vc_enable(dsidev, channel, true); 3986 + dsi_if_enable(dsidev, true); 3987 + } 4014 3988 4015 - dssdev->manager->enable(dssdev->manager); 3989 + r = dss_mgr_enable(dssdev->manager); 3990 + if (r) { 3991 + if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { 3992 + dsi_if_enable(dsidev, false); 3993 + dsi_vc_enable(dsidev, channel, false); 3994 + } 3995 + 3996 + return r; 3997 + } 4016 3998 4017 3999 return 0; 4018 4000 } 4019 - EXPORT_SYMBOL(dsi_video_mode_enable); 4001 + EXPORT_SYMBOL(dsi_enable_video_output); 4020 4002 4021 - void dsi_video_mode_disable(struct omap_dss_device *dssdev, int channel) 4003 + void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel) 4022 4004 { 4023 4005 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4024 4006 4025 - dsi_if_enable(dsidev, false); 4026 - dsi_vc_enable(dsidev, channel, false); 4007 + if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) { 4008 + dsi_if_enable(dsidev, false); 4009 + dsi_vc_enable(dsidev, channel, false); 4027 4010 4028 - /* MODE, 0 = command mode */ 4029 - REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 4, 4); 4011 + /* MODE, 0 = command mode */ 4012 + REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 4, 4); 4030 4013 4031 - dsi_vc_enable(dsidev, channel, true); 4032 - dsi_if_enable(dsidev, true); 4014 + dsi_vc_enable(dsidev, channel, true); 4015 + dsi_if_enable(dsidev, true); 4016 + } 4033 4017 4034 - dssdev->manager->disable(dssdev->manager); 4018 + dss_mgr_disable(dssdev->manager); 4035 4019 } 4036 - EXPORT_SYMBOL(dsi_video_mode_disable); 4020 + EXPORT_SYMBOL(dsi_disable_video_output); 4037 4021 4038 4022 static void dsi_update_screen_dispc(struct omap_dss_device *dssdev, 4039 - u16 x, u16 y, u16 w, u16 h) 4023 + u16 w, u16 h) 4040 4024 { 4041 4025 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4042 4026 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); ··· 4065 4021 const unsigned channel = dsi->update_channel; 4066 4022 const unsigned line_buf_size = dsi_get_line_buf_size(dsidev); 4067 4023 4068 - DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n", 4069 - x, y, w, h); 4024 + DSSDBG("dsi_update_screen_dispc(%dx%d)\n", w, h); 4070 4025 4071 4026 dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP); 4072 4027 ··· 4113 4070 msecs_to_jiffies(250)); 4114 4071 BUG_ON(r == 0); 4115 4072 4116 - dss_start_update(dssdev); 4073 + dss_mgr_start_update(dssdev->manager); 4117 4074 4118 4075 if (dsi->te_enabled) { 4119 4076 /* disable LP_RX_TO, so that we can receive TE. Time to wait ··· 4189 4146 #endif 4190 4147 } 4191 4148 4192 - int omap_dsi_prepare_update(struct omap_dss_device *dssdev, 4193 - u16 *x, u16 *y, u16 *w, u16 *h, 4194 - bool enlarge_update_area) 4195 - { 4196 - struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4197 - u16 dw, dh; 4198 - 4199 - dssdev->driver->get_resolution(dssdev, &dw, &dh); 4200 - 4201 - if (*x > dw || *y > dh) 4202 - return -EINVAL; 4203 - 4204 - if (*x + *w > dw) 4205 - return -EINVAL; 4206 - 4207 - if (*y + *h > dh) 4208 - return -EINVAL; 4209 - 4210 - if (*w == 1) 4211 - return -EINVAL; 4212 - 4213 - if (*w == 0 || *h == 0) 4214 - return -EINVAL; 4215 - 4216 - dsi_perf_mark_setup(dsidev); 4217 - 4218 - dss_setup_partial_planes(dssdev, x, y, w, h, 4219 - enlarge_update_area); 4220 - dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h); 4221 - 4222 - return 0; 4223 - } 4224 - EXPORT_SYMBOL(omap_dsi_prepare_update); 4225 - 4226 - int omap_dsi_update(struct omap_dss_device *dssdev, 4227 - int channel, 4228 - u16 x, u16 y, u16 w, u16 h, 4149 + int omap_dsi_update(struct omap_dss_device *dssdev, int channel, 4229 4150 void (*callback)(int, void *), void *data) 4230 4151 { 4231 4152 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4232 4153 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4154 + u16 dw, dh; 4155 + 4156 + dsi_perf_mark_setup(dsidev); 4233 4157 4234 4158 dsi->update_channel = channel; 4235 - 4236 - /* OMAP DSS cannot send updates of odd widths. 4237 - * omap_dsi_prepare_update() makes the widths even, but add a BUG_ON 4238 - * here to make sure we catch erroneous updates. Otherwise we'll only 4239 - * see rather obscure HW error happening, as DSS halts. */ 4240 - BUG_ON(x % 2 == 1); 4241 4159 4242 4160 dsi->framedone_callback = callback; 4243 4161 dsi->framedone_data = data; 4244 4162 4245 - dsi->update_region.x = x; 4246 - dsi->update_region.y = y; 4247 - dsi->update_region.w = w; 4248 - dsi->update_region.h = h; 4249 - dsi->update_region.device = dssdev; 4163 + dssdev->driver->get_resolution(dssdev, &dw, &dh); 4250 4164 4251 - dsi_update_screen_dispc(dssdev, x, y, w, h); 4165 + #ifdef DEBUG 4166 + dsi->update_bytes = dw * dh * 4167 + dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8; 4168 + #endif 4169 + dsi_update_screen_dispc(dssdev, dw, dh); 4252 4170 4253 4171 return 0; 4254 4172 } ··· 4222 4218 int r; 4223 4219 4224 4220 if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) { 4221 + u16 dw, dh; 4225 4222 u32 irq; 4226 4223 struct omap_video_timings timings = { 4227 4224 .hsw = 1, ··· 4232 4227 .vfp = 0, 4233 4228 .vbp = 0, 4234 4229 }; 4230 + 4231 + dssdev->driver->get_resolution(dssdev, &dw, &dh); 4232 + timings.x_res = dw; 4233 + timings.y_res = dh; 4235 4234 4236 4235 irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ? 4237 4236 DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2; ··· 4338 4329 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4339 4330 int dsi_module = dsi_get_dsidev_id(dsidev); 4340 4331 int r; 4332 + 4333 + r = dsi_parse_lane_config(dssdev); 4334 + if (r) { 4335 + DSSERR("illegal lane config"); 4336 + goto err0; 4337 + } 4341 4338 4342 4339 r = dsi_pll_init(dsidev, true, true); 4343 4340 if (r) ··· 4536 4521 { 4537 4522 struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); 4538 4523 struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); 4539 - int dsi_module = dsi_get_dsidev_id(dsidev); 4540 4524 4541 4525 DSSDBG("DSI init\n"); 4542 4526 ··· 4555 4541 } 4556 4542 4557 4543 dsi->vdds_dsi_reg = vdds_dsi; 4558 - } 4559 - 4560 - if (dsi_get_num_data_lanes_dssdev(dssdev) > dsi->num_data_lanes) { 4561 - DSSERR("DSI%d can't support more than %d data lanes\n", 4562 - dsi_module + 1, dsi->num_data_lanes); 4563 - return -EINVAL; 4564 4544 } 4565 4545 4566 4546 return 0; ··· 4779 4771 dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n", 4780 4772 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); 4781 4773 4782 - dsi->num_data_lanes = dsi_get_num_data_lanes(dsidev); 4774 + /* DSI on OMAP3 doesn't have register DSI_GNQ, set number 4775 + * of data to 3 by default */ 4776 + if (dss_has_feature(FEAT_DSI_GNQ)) 4777 + /* NB_DATA_LANES */ 4778 + dsi->num_lanes_supported = 1 + REG_GET(dsidev, DSI_GNQ, 11, 9); 4779 + else 4780 + dsi->num_lanes_supported = 3; 4783 4781 4784 4782 dsi_runtime_put(dsidev); 4785 4783
+47 -27
drivers/video/omap2/dss/dss.h
··· 163 163 struct regulator *dss_get_vdds_dsi(void); 164 164 struct regulator *dss_get_vdds_sdi(void); 165 165 166 + /* apply */ 167 + void dss_apply_init(void); 168 + int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr); 169 + int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl); 170 + void dss_mgr_start_update(struct omap_overlay_manager *mgr); 171 + int omap_dss_mgr_apply(struct omap_overlay_manager *mgr); 172 + 173 + int dss_mgr_enable(struct omap_overlay_manager *mgr); 174 + void dss_mgr_disable(struct omap_overlay_manager *mgr); 175 + int dss_mgr_set_info(struct omap_overlay_manager *mgr, 176 + struct omap_overlay_manager_info *info); 177 + void dss_mgr_get_info(struct omap_overlay_manager *mgr, 178 + struct omap_overlay_manager_info *info); 179 + int dss_mgr_set_device(struct omap_overlay_manager *mgr, 180 + struct omap_dss_device *dssdev); 181 + int dss_mgr_unset_device(struct omap_overlay_manager *mgr); 182 + 183 + bool dss_ovl_is_enabled(struct omap_overlay *ovl); 184 + int dss_ovl_enable(struct omap_overlay *ovl); 185 + int dss_ovl_disable(struct omap_overlay *ovl); 186 + int dss_ovl_set_info(struct omap_overlay *ovl, 187 + struct omap_overlay_info *info); 188 + void dss_ovl_get_info(struct omap_overlay *ovl, 189 + struct omap_overlay_info *info); 190 + int dss_ovl_set_manager(struct omap_overlay *ovl, 191 + struct omap_overlay_manager *mgr); 192 + int dss_ovl_unset_manager(struct omap_overlay *ovl); 193 + 166 194 /* display */ 167 195 int dss_suspend_all_devices(void); 168 196 int dss_resume_all_devices(void); ··· 209 181 /* manager */ 210 182 int dss_init_overlay_managers(struct platform_device *pdev); 211 183 void dss_uninit_overlay_managers(struct platform_device *pdev); 212 - int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl); 213 - void dss_setup_partial_planes(struct omap_dss_device *dssdev, 214 - u16 *x, u16 *y, u16 *w, u16 *h, 215 - bool enlarge_update_area); 216 - void dss_start_update(struct omap_dss_device *dssdev); 184 + int dss_mgr_simple_check(struct omap_overlay_manager *mgr, 185 + const struct omap_overlay_manager_info *info); 186 + int dss_mgr_check(struct omap_overlay_manager *mgr, 187 + struct omap_dss_device *dssdev, 188 + struct omap_overlay_manager_info *info, 189 + struct omap_overlay_info **overlay_infos); 217 190 218 191 /* overlay */ 219 192 void dss_init_overlays(struct platform_device *pdev); 220 193 void dss_uninit_overlays(struct platform_device *pdev); 221 - int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev); 222 194 void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr); 223 - #ifdef L4_EXAMPLE 224 - void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr); 225 - #endif 226 195 void dss_recheck_connections(struct omap_dss_device *dssdev, bool force); 196 + int dss_ovl_simple_check(struct omap_overlay *ovl, 197 + const struct omap_overlay_info *info); 198 + int dss_ovl_check(struct omap_overlay *ovl, 199 + struct omap_overlay_info *info, struct omap_dss_device *dssdev); 227 200 228 201 /* DSS */ 229 202 int dss_init_platform_driver(void); ··· 428 399 struct dispc_clock_info *cinfo); 429 400 430 401 402 + void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high); 431 403 u32 dispc_ovl_get_fifo_size(enum omap_plane plane); 432 404 u32 dispc_ovl_get_burst_size(enum omap_plane plane); 433 405 int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, 434 - bool ilace, enum omap_channel channel, bool replication, 435 - u32 fifo_low, u32 fifo_high); 406 + bool ilace, bool replication); 436 407 int dispc_ovl_enable(enum omap_plane plane, bool enable); 437 - 408 + void dispc_ovl_set_channel_out(enum omap_plane plane, 409 + enum omap_channel channel); 438 410 439 411 void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable); 440 412 void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height); 441 - void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable); 442 - void dispc_mgr_set_cpr_coef(enum omap_channel channel, 443 - struct omap_dss_cpr_coefs *coefs); 413 + u32 dispc_mgr_get_vsync_irq(enum omap_channel channel); 414 + u32 dispc_mgr_get_framedone_irq(enum omap_channel channel); 444 415 bool dispc_mgr_go_busy(enum omap_channel channel); 445 416 void dispc_mgr_go(enum omap_channel channel); 417 + bool dispc_mgr_is_enabled(enum omap_channel channel); 446 418 void dispc_mgr_enable(enum omap_channel channel, bool enable); 447 419 bool dispc_mgr_is_channel_enabled(enum omap_channel channel); 448 420 void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode); ··· 451 421 void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines); 452 422 void dispc_mgr_set_lcd_display_type(enum omap_channel channel, 453 423 enum omap_lcd_display_type type); 454 - void dispc_mgr_set_default_color(enum omap_channel channel, u32 color); 455 - u32 dispc_mgr_get_default_color(enum omap_channel channel); 456 - void dispc_mgr_set_trans_key(enum omap_channel ch, 457 - enum omap_dss_trans_key_type type, 458 - u32 trans_key); 459 - void dispc_mgr_get_trans_key(enum omap_channel ch, 460 - enum omap_dss_trans_key_type *type, 461 - u32 *trans_key); 462 - void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable); 463 - void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable); 464 - bool dispc_mgr_trans_key_enabled(enum omap_channel ch); 465 - bool dispc_mgr_alpha_fixed_zorder_enabled(enum omap_channel ch); 466 424 void dispc_mgr_set_lcd_timings(enum omap_channel channel, 467 425 struct omap_video_timings *timings); 468 426 void dispc_mgr_set_pol_freq(enum omap_channel channel, ··· 461 443 struct dispc_clock_info *cinfo); 462 444 int dispc_mgr_get_clock_div(enum omap_channel channel, 463 445 struct dispc_clock_info *cinfo); 446 + void dispc_mgr_setup(enum omap_channel channel, 447 + struct omap_overlay_manager_info *info); 464 448 465 449 /* VENC */ 466 450 #ifdef CONFIG_OMAP2_DSS_VENC
+11
drivers/video/omap2/dss/dss_features.c
··· 304 304 [FEAT_PARAM_DSIPLL_FINT] = { 0, 0 }, 305 305 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, 0 }, 306 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 309 314 static const struct dss_param_range omap3_dss_param_range[] = { ··· 321 316 [FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 }, 322 317 [FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1}, 323 318 [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, 319 + [FEAT_PARAM_LINEWIDTH] = { 1, 1024 }, 324 320 }; 325 321 326 322 static const struct dss_param_range omap4_dss_param_range[] = { ··· 334 328 [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 }, 335 329 [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, 336 330 [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, 331 + [FEAT_PARAM_LINEWIDTH] = { 1, 2048 }, 337 332 }; 338 333 339 334 /* OMAP2 DSS Features */ ··· 472 465 .dump_core = ti_hdmi_4xxx_core_dump, 473 466 .dump_pll = ti_hdmi_4xxx_pll_dump, 474 467 .dump_phy = ti_hdmi_4xxx_phy_dump, 468 + #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ 469 + defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) 470 + .audio_enable = ti_hdmi_4xxx_wp_audio_enable, 471 + #endif 475 472 476 473 }; 477 474
+1
drivers/video/omap2/dss/dss_features.h
··· 86 86 FEAT_PARAM_DSIPLL_FINT, 87 87 FEAT_PARAM_DSIPLL_LPDIV, 88 88 FEAT_PARAM_DOWNSCALE, 89 + FEAT_PARAM_LINEWIDTH, 89 90 }; 90 91 91 92 /* DSS Feature Functions */
+54 -5
drivers/video/omap2/dss/hdmi.c
··· 333 333 if (r) 334 334 return r; 335 335 336 - dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 0); 336 + dss_mgr_disable(dssdev->manager); 337 337 338 338 p = &dssdev->panel.timings; 339 339 ··· 387 387 388 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 394 return 0; 395 + 396 + err_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); 393 400 err: 394 401 hdmi_runtime_put(); 395 402 return -EIO; ··· 404 397 405 398 static void hdmi_power_off(struct omap_dss_device *dssdev) 406 399 { 407 - dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 0); 400 + dss_mgr_disable(dssdev->manager); 408 401 409 402 hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0); 410 403 hdmi.ip_data.ops->phy_disable(&hdmi.ip_data); ··· 561 554 #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ 562 555 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) 563 556 564 - static int hdmi_audio_hw_params(struct hdmi_ip_data *ip_data, 565 - struct snd_pcm_substream *substream, 557 + static int hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd, 558 + struct snd_soc_dai *dai) 559 + { 560 + struct snd_soc_pcm_runtime *rtd = substream->private_data; 561 + struct snd_soc_codec *codec = rtd->codec; 562 + struct platform_device *pdev = to_platform_device(codec->dev); 563 + struct hdmi_ip_data *ip_data = snd_soc_codec_get_drvdata(codec); 564 + int err = 0; 565 + 566 + if (!(ip_data->ops) && !(ip_data->ops->audio_enable)) { 567 + dev_err(&pdev->dev, "Cannot enable/disable audio\n"); 568 + return -ENODEV; 569 + } 570 + 571 + switch (cmd) { 572 + case SNDRV_PCM_TRIGGER_START: 573 + case SNDRV_PCM_TRIGGER_RESUME: 574 + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 575 + ip_data->ops->audio_enable(ip_data, true); 576 + break; 577 + case SNDRV_PCM_TRIGGER_STOP: 578 + case SNDRV_PCM_TRIGGER_SUSPEND: 579 + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 580 + ip_data->ops->audio_enable(ip_data, false); 581 + break; 582 + default: 583 + err = -EINVAL; 584 + } 585 + return err; 586 + } 587 + 588 + static int hdmi_audio_hw_params(struct snd_pcm_substream *substream, 566 589 struct snd_pcm_hw_params *params, 567 590 struct snd_soc_dai *dai) 568 591 { 592 + struct snd_soc_pcm_runtime *rtd = substream->private_data; 593 + struct snd_soc_codec *codec = rtd->codec; 594 + struct hdmi_ip_data *ip_data = snd_soc_codec_get_drvdata(codec); 569 595 struct hdmi_audio_format audio_format; 570 596 struct hdmi_audio_dma audio_dma; 571 597 struct hdmi_core_audio_config core_cfg; ··· 738 698 return 0; 739 699 } 740 700 701 + static int hdmi_audio_codec_probe(struct snd_soc_codec *codec) 702 + { 703 + struct hdmi_ip_data *priv = &hdmi.ip_data; 704 + 705 + snd_soc_codec_set_drvdata(codec, priv); 706 + return 0; 707 + } 708 + 741 709 static struct snd_soc_codec_driver hdmi_audio_codec_drv = { 710 + .probe = hdmi_audio_codec_probe, 742 711 }; 743 712 744 713 static struct snd_soc_dai_ops hdmi_audio_codec_ops = {
+133 -1102
drivers/video/omap2/dss/manager.c
··· 26 26 #include <linux/slab.h> 27 27 #include <linux/module.h> 28 28 #include <linux/platform_device.h> 29 - #include <linux/spinlock.h> 30 29 #include <linux/jiffies.h> 31 30 32 31 #include <video/omapdss.h> 33 - #include <plat/cpu.h> 34 32 35 33 #include "dss.h" 36 34 #include "dss_features.h" 37 35 38 36 static int num_managers; 39 - static struct list_head manager_list; 37 + static struct omap_overlay_manager *managers; 40 38 41 39 static ssize_t manager_name_show(struct omap_overlay_manager *mgr, char *buf) 42 40 { ··· 104 106 static ssize_t manager_default_color_show(struct omap_overlay_manager *mgr, 105 107 char *buf) 106 108 { 107 - return snprintf(buf, PAGE_SIZE, "%#x\n", mgr->info.default_color); 109 + struct omap_overlay_manager_info info; 110 + 111 + mgr->get_manager_info(mgr, &info); 112 + 113 + return snprintf(buf, PAGE_SIZE, "%#x\n", info.default_color); 108 114 } 109 115 110 116 static ssize_t manager_default_color_store(struct omap_overlay_manager *mgr, ··· 146 144 char *buf) 147 145 { 148 146 enum omap_dss_trans_key_type key_type; 147 + struct omap_overlay_manager_info info; 149 148 150 - key_type = mgr->info.trans_key_type; 149 + mgr->get_manager_info(mgr, &info); 150 + 151 + key_type = info.trans_key_type; 151 152 BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str)); 152 153 153 154 return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]); ··· 190 185 static ssize_t manager_trans_key_value_show(struct omap_overlay_manager *mgr, 191 186 char *buf) 192 187 { 193 - return snprintf(buf, PAGE_SIZE, "%#x\n", mgr->info.trans_key); 188 + struct omap_overlay_manager_info info; 189 + 190 + mgr->get_manager_info(mgr, &info); 191 + 192 + return snprintf(buf, PAGE_SIZE, "%#x\n", info.trans_key); 194 193 } 195 194 196 195 static ssize_t manager_trans_key_value_store(struct omap_overlay_manager *mgr, ··· 226 217 static ssize_t manager_trans_key_enabled_show(struct omap_overlay_manager *mgr, 227 218 char *buf) 228 219 { 229 - return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.trans_enabled); 220 + struct omap_overlay_manager_info info; 221 + 222 + mgr->get_manager_info(mgr, &info); 223 + 224 + return snprintf(buf, PAGE_SIZE, "%d\n", info.trans_enabled); 230 225 } 231 226 232 227 static ssize_t manager_trans_key_enabled_store(struct omap_overlay_manager *mgr, ··· 262 249 static ssize_t manager_alpha_blending_enabled_show( 263 250 struct omap_overlay_manager *mgr, char *buf) 264 251 { 252 + struct omap_overlay_manager_info info; 253 + 254 + mgr->get_manager_info(mgr, &info); 255 + 265 256 WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)); 266 257 267 258 return snprintf(buf, PAGE_SIZE, "%d\n", 268 - mgr->info.partial_alpha_enabled); 259 + info.partial_alpha_enabled); 269 260 } 270 261 271 262 static ssize_t manager_alpha_blending_enabled_store( ··· 304 287 static ssize_t manager_cpr_enable_show(struct omap_overlay_manager *mgr, 305 288 char *buf) 306 289 { 307 - return snprintf(buf, PAGE_SIZE, "%d\n", mgr->info.cpr_enable); 290 + struct omap_overlay_manager_info info; 291 + 292 + mgr->get_manager_info(mgr, &info); 293 + 294 + return snprintf(buf, PAGE_SIZE, "%d\n", info.cpr_enable); 308 295 } 309 296 310 297 static ssize_t manager_cpr_enable_store(struct omap_overlay_manager *mgr, ··· 490 469 .default_attrs = manager_sysfs_attrs, 491 470 }; 492 471 493 - /* 494 - * We have 4 levels of cache for the dispc settings. First two are in SW and 495 - * the latter two in HW. 496 - * 497 - * +--------------------+ 498 - * |overlay/manager_info| 499 - * +--------------------+ 500 - * v 501 - * apply() 502 - * v 503 - * +--------------------+ 504 - * | dss_cache | 505 - * +--------------------+ 506 - * v 507 - * configure() 508 - * v 509 - * +--------------------+ 510 - * | shadow registers | 511 - * +--------------------+ 512 - * v 513 - * VFP or lcd/digit_enable 514 - * v 515 - * +--------------------+ 516 - * | registers | 517 - * +--------------------+ 518 - */ 519 - 520 - struct overlay_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 - bool enabled; 530 - 531 - struct omap_overlay_info info; 532 - 533 - enum omap_channel channel; 534 - bool replication; 535 - bool ilace; 536 - 537 - u32 fifo_low; 538 - u32 fifo_high; 539 - }; 540 - 541 - struct manager_cache_data { 542 - /* If true, cache changed, but not written to shadow registers. Set 543 - * in apply(), cleared when registers written. */ 544 - bool dirty; 545 - /* If true, shadow registers contain changed values not yet in real 546 - * registers. Set when writing to shadow registers, cleared at 547 - * VSYNC/EVSYNC */ 548 - bool shadow_dirty; 549 - 550 - struct omap_overlay_manager_info info; 551 - 552 - bool manual_update; 553 - bool do_manual_update; 554 - 555 - /* manual update region */ 556 - u16 x, y, w, h; 557 - 558 - /* enlarge the update area if the update area contains scaled 559 - * overlays */ 560 - bool enlarge_update_area; 561 - }; 562 - 563 - static struct { 564 - spinlock_t lock; 565 - struct overlay_cache_data overlay_cache[MAX_DSS_OVERLAYS]; 566 - struct manager_cache_data manager_cache[MAX_DSS_MANAGERS]; 567 - 568 - bool irq_enabled; 569 - } dss_cache; 570 - 571 - 572 - 573 - static int omap_dss_set_device(struct omap_overlay_manager *mgr, 574 - struct omap_dss_device *dssdev) 575 - { 576 - int i; 577 - int r; 578 - 579 - if (dssdev->manager) { 580 - DSSERR("display '%s' already has a manager '%s'\n", 581 - dssdev->name, dssdev->manager->name); 582 - return -EINVAL; 583 - } 584 - 585 - if ((mgr->supported_displays & dssdev->type) == 0) { 586 - DSSERR("display '%s' does not support manager '%s'\n", 587 - dssdev->name, mgr->name); 588 - return -EINVAL; 589 - } 590 - 591 - for (i = 0; i < mgr->num_overlays; i++) { 592 - struct omap_overlay *ovl = mgr->overlays[i]; 593 - 594 - if (ovl->manager != mgr || !ovl->info.enabled) 595 - continue; 596 - 597 - r = dss_check_overlay(ovl, dssdev); 598 - if (r) 599 - return r; 600 - } 601 - 602 - dssdev->manager = mgr; 603 - mgr->device = dssdev; 604 - mgr->device_changed = true; 605 - 606 - return 0; 607 - } 608 - 609 - static int omap_dss_unset_device(struct omap_overlay_manager *mgr) 610 - { 611 - if (!mgr->device) { 612 - DSSERR("failed to unset display, display not set.\n"); 613 - return -EINVAL; 614 - } 615 - 616 - /* 617 - * Don't allow currently enabled displays to have the overlay manager 618 - * pulled out from underneath them 619 - */ 620 - if (mgr->device->state != OMAP_DSS_DISPLAY_DISABLED) 621 - return -EINVAL; 622 - 623 - mgr->device->manager = NULL; 624 - mgr->device = NULL; 625 - mgr->device_changed = true; 626 - 627 - return 0; 628 - } 629 - 630 472 static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr) 631 473 { 632 474 unsigned long timeout = msecs_to_jiffies(500); ··· 508 624 return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); 509 625 } 510 626 511 - static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr) 512 - { 513 - unsigned long timeout = msecs_to_jiffies(500); 514 - struct manager_cache_data *mc; 515 - u32 irq; 516 - int r; 517 - int i; 518 - struct omap_dss_device *dssdev = mgr->device; 519 - 520 - if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) 521 - return 0; 522 - 523 - if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) 524 - return 0; 525 - 526 - if (dssdev->type == OMAP_DISPLAY_TYPE_VENC 527 - || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) { 528 - irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; 529 - } else { 530 - irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ? 531 - DISPC_IRQ_VSYNC : DISPC_IRQ_VSYNC2; 532 - } 533 - 534 - mc = &dss_cache.manager_cache[mgr->id]; 535 - i = 0; 536 - while (1) { 537 - unsigned long flags; 538 - bool shadow_dirty, dirty; 539 - 540 - spin_lock_irqsave(&dss_cache.lock, flags); 541 - dirty = mc->dirty; 542 - shadow_dirty = mc->shadow_dirty; 543 - spin_unlock_irqrestore(&dss_cache.lock, flags); 544 - 545 - if (!dirty && !shadow_dirty) { 546 - r = 0; 547 - break; 548 - } 549 - 550 - /* 4 iterations is the worst case: 551 - * 1 - initial iteration, dirty = true (between VFP and VSYNC) 552 - * 2 - first VSYNC, dirty = true 553 - * 3 - dirty = false, shadow_dirty = true 554 - * 4 - shadow_dirty = false */ 555 - if (i++ == 3) { 556 - DSSERR("mgr(%d)->wait_for_go() not finishing\n", 557 - mgr->id); 558 - r = 0; 559 - break; 560 - } 561 - 562 - r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); 563 - if (r == -ERESTARTSYS) 564 - break; 565 - 566 - if (r) { 567 - DSSERR("mgr(%d)->wait_for_go() timeout\n", mgr->id); 568 - break; 569 - } 570 - } 571 - 572 - return r; 573 - } 574 - 575 - int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl) 576 - { 577 - unsigned long timeout = msecs_to_jiffies(500); 578 - struct overlay_cache_data *oc; 579 - struct omap_dss_device *dssdev; 580 - u32 irq; 581 - int r; 582 - int i; 583 - 584 - if (!ovl->manager) 585 - return 0; 586 - 587 - dssdev = ovl->manager->device; 588 - 589 - if (!dssdev || dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) 590 - return 0; 591 - 592 - if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) 593 - return 0; 594 - 595 - if (dssdev->type == OMAP_DISPLAY_TYPE_VENC 596 - || dssdev->type == OMAP_DISPLAY_TYPE_HDMI) { 597 - irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN; 598 - } else { 599 - irq = (dssdev->manager->id == OMAP_DSS_CHANNEL_LCD) ? 600 - DISPC_IRQ_VSYNC : DISPC_IRQ_VSYNC2; 601 - } 602 - 603 - oc = &dss_cache.overlay_cache[ovl->id]; 604 - i = 0; 605 - while (1) { 606 - unsigned long flags; 607 - bool shadow_dirty, dirty; 608 - 609 - spin_lock_irqsave(&dss_cache.lock, flags); 610 - dirty = oc->dirty; 611 - shadow_dirty = oc->shadow_dirty; 612 - spin_unlock_irqrestore(&dss_cache.lock, flags); 613 - 614 - if (!dirty && !shadow_dirty) { 615 - r = 0; 616 - break; 617 - } 618 - 619 - /* 4 iterations is the worst case: 620 - * 1 - initial iteration, dirty = true (between VFP and VSYNC) 621 - * 2 - first VSYNC, dirty = true 622 - * 3 - dirty = false, shadow_dirty = true 623 - * 4 - shadow_dirty = false */ 624 - if (i++ == 3) { 625 - DSSERR("ovl(%d)->wait_for_go() not finishing\n", 626 - ovl->id); 627 - r = 0; 628 - break; 629 - } 630 - 631 - r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); 632 - if (r == -ERESTARTSYS) 633 - break; 634 - 635 - if (r) { 636 - DSSERR("ovl(%d)->wait_for_go() timeout\n", ovl->id); 637 - break; 638 - } 639 - } 640 - 641 - return r; 642 - } 643 - 644 - static int overlay_enabled(struct omap_overlay *ovl) 645 - { 646 - return ovl->info.enabled && ovl->manager && ovl->manager->device; 647 - } 648 - 649 - /* Is rect1 a subset of rect2? */ 650 - static bool rectangle_subset(int x1, int y1, int w1, int h1, 651 - int x2, int y2, int w2, int h2) 652 - { 653 - if (x1 < x2 || y1 < y2) 654 - return false; 655 - 656 - if (x1 + w1 > x2 + w2) 657 - return false; 658 - 659 - if (y1 + h1 > y2 + h2) 660 - return false; 661 - 662 - return true; 663 - } 664 - 665 - /* Do rect1 and rect2 overlap? */ 666 - static bool rectangle_intersects(int x1, int y1, int w1, int h1, 667 - int x2, int y2, int w2, int h2) 668 - { 669 - if (x1 >= x2 + w2) 670 - return false; 671 - 672 - if (x2 >= x1 + w1) 673 - return false; 674 - 675 - if (y1 >= y2 + h2) 676 - return false; 677 - 678 - if (y2 >= y1 + h1) 679 - return false; 680 - 681 - return true; 682 - } 683 - 684 - static bool dispc_is_overlay_scaled(struct overlay_cache_data *oc) 685 - { 686 - struct omap_overlay_info *oi = &oc->info; 687 - 688 - if (oi->out_width != 0 && oi->width != oi->out_width) 689 - return true; 690 - 691 - if (oi->out_height != 0 && oi->height != oi->out_height) 692 - return true; 693 - 694 - return false; 695 - } 696 - 697 - static int configure_overlay(enum omap_plane plane) 698 - { 699 - struct overlay_cache_data *c; 700 - struct manager_cache_data *mc; 701 - struct omap_overlay_info *oi, new_oi; 702 - struct omap_overlay_manager_info *mi; 703 - u16 outw, outh; 704 - u16 x, y, w, h; 705 - u32 paddr; 706 - int r; 707 - u16 orig_w, orig_h, orig_outw, orig_outh; 708 - 709 - DSSDBGF("%d", plane); 710 - 711 - c = &dss_cache.overlay_cache[plane]; 712 - oi = &c->info; 713 - 714 - if (!c->enabled) { 715 - dispc_ovl_enable(plane, 0); 716 - return 0; 717 - } 718 - 719 - mc = &dss_cache.manager_cache[c->channel]; 720 - mi = &mc->info; 721 - 722 - x = oi->pos_x; 723 - y = oi->pos_y; 724 - w = oi->width; 725 - h = oi->height; 726 - outw = oi->out_width == 0 ? oi->width : oi->out_width; 727 - outh = oi->out_height == 0 ? oi->height : oi->out_height; 728 - paddr = oi->paddr; 729 - 730 - orig_w = w; 731 - orig_h = h; 732 - orig_outw = outw; 733 - orig_outh = outh; 734 - 735 - if (mc->manual_update && mc->do_manual_update) { 736 - unsigned bpp; 737 - unsigned scale_x_m = w, scale_x_d = outw; 738 - unsigned scale_y_m = h, scale_y_d = outh; 739 - 740 - /* If the overlay is outside the update region, disable it */ 741 - if (!rectangle_intersects(mc->x, mc->y, mc->w, mc->h, 742 - x, y, outw, outh)) { 743 - dispc_ovl_enable(plane, 0); 744 - return 0; 745 - } 746 - 747 - switch (oi->color_mode) { 748 - case OMAP_DSS_COLOR_NV12: 749 - bpp = 8; 750 - break; 751 - case OMAP_DSS_COLOR_RGB16: 752 - case OMAP_DSS_COLOR_ARGB16: 753 - case OMAP_DSS_COLOR_YUV2: 754 - case OMAP_DSS_COLOR_UYVY: 755 - case OMAP_DSS_COLOR_RGBA16: 756 - case OMAP_DSS_COLOR_RGBX16: 757 - case OMAP_DSS_COLOR_ARGB16_1555: 758 - case OMAP_DSS_COLOR_XRGB16_1555: 759 - bpp = 16; 760 - break; 761 - 762 - case OMAP_DSS_COLOR_RGB24P: 763 - bpp = 24; 764 - break; 765 - 766 - case OMAP_DSS_COLOR_RGB24U: 767 - case OMAP_DSS_COLOR_ARGB32: 768 - case OMAP_DSS_COLOR_RGBA32: 769 - case OMAP_DSS_COLOR_RGBX32: 770 - bpp = 32; 771 - break; 772 - 773 - default: 774 - BUG(); 775 - } 776 - 777 - if (mc->x > oi->pos_x) { 778 - x = 0; 779 - outw -= (mc->x - oi->pos_x); 780 - paddr += (mc->x - oi->pos_x) * 781 - scale_x_m / scale_x_d * bpp / 8; 782 - } else { 783 - x = oi->pos_x - mc->x; 784 - } 785 - 786 - if (mc->y > oi->pos_y) { 787 - y = 0; 788 - outh -= (mc->y - oi->pos_y); 789 - paddr += (mc->y - oi->pos_y) * 790 - scale_y_m / scale_y_d * 791 - oi->screen_width * bpp / 8; 792 - } else { 793 - y = oi->pos_y - mc->y; 794 - } 795 - 796 - if (mc->w < (x + outw)) 797 - outw -= (x + outw) - (mc->w); 798 - 799 - if (mc->h < (y + outh)) 800 - outh -= (y + outh) - (mc->h); 801 - 802 - w = w * outw / orig_outw; 803 - h = h * outh / orig_outh; 804 - 805 - /* YUV mode overlay's input width has to be even and the 806 - * algorithm above may adjust the width to be odd. 807 - * 808 - * Here we adjust the width if needed, preferring to increase 809 - * the width if the original width was bigger. 810 - */ 811 - if ((w & 1) && 812 - (oi->color_mode == OMAP_DSS_COLOR_YUV2 || 813 - oi->color_mode == OMAP_DSS_COLOR_UYVY)) { 814 - if (orig_w > w) 815 - w += 1; 816 - else 817 - w -= 1; 818 - } 819 - } 820 - 821 - new_oi = *oi; 822 - 823 - /* update new_oi members which could have been possibly updated */ 824 - new_oi.pos_x = x; 825 - new_oi.pos_y = y; 826 - new_oi.width = w; 827 - new_oi.height = h; 828 - new_oi.out_width = outw; 829 - new_oi.out_height = outh; 830 - new_oi.paddr = paddr; 831 - 832 - r = dispc_ovl_setup(plane, &new_oi, c->ilace, c->channel, 833 - c->replication, c->fifo_low, c->fifo_high); 834 - if (r) { 835 - /* this shouldn't happen */ 836 - DSSERR("dispc_ovl_setup failed for ovl %d\n", plane); 837 - dispc_ovl_enable(plane, 0); 838 - return r; 839 - } 840 - 841 - dispc_ovl_enable(plane, 1); 842 - 843 - return 0; 844 - } 845 - 846 - static void configure_manager(enum omap_channel channel) 847 - { 848 - struct omap_overlay_manager_info *mi; 849 - 850 - DSSDBGF("%d", channel); 851 - 852 - /* picking info from the cache */ 853 - mi = &dss_cache.manager_cache[channel].info; 854 - 855 - dispc_mgr_set_default_color(channel, mi->default_color); 856 - dispc_mgr_set_trans_key(channel, mi->trans_key_type, mi->trans_key); 857 - dispc_mgr_enable_trans_key(channel, mi->trans_enabled); 858 - dispc_mgr_enable_alpha_fixed_zorder(channel, mi->partial_alpha_enabled); 859 - if (dss_has_feature(FEAT_CPR)) { 860 - dispc_mgr_enable_cpr(channel, mi->cpr_enable); 861 - dispc_mgr_set_cpr_coef(channel, &mi->cpr_coefs); 862 - } 863 - } 864 - 865 - /* configure_dispc() tries to write values from cache to shadow registers. 866 - * It writes only to those managers/overlays that are not busy. 867 - * returns 0 if everything could be written to shadow registers. 868 - * returns 1 if not everything could be written to shadow registers. */ 869 - static int configure_dispc(void) 870 - { 871 - struct overlay_cache_data *oc; 872 - struct manager_cache_data *mc; 873 - const int num_ovls = dss_feat_get_num_ovls(); 874 - const int num_mgrs = dss_feat_get_num_mgrs(); 875 - int i; 876 - int r; 877 - bool mgr_busy[MAX_DSS_MANAGERS]; 878 - bool mgr_go[MAX_DSS_MANAGERS]; 879 - bool busy; 880 - 881 - r = 0; 882 - busy = false; 883 - 884 - for (i = 0; i < num_mgrs; i++) { 885 - mgr_busy[i] = dispc_mgr_go_busy(i); 886 - mgr_go[i] = false; 887 - } 888 - 889 - /* Commit overlay settings */ 890 - for (i = 0; i < num_ovls; ++i) { 891 - oc = &dss_cache.overlay_cache[i]; 892 - mc = &dss_cache.manager_cache[oc->channel]; 893 - 894 - if (!oc->dirty) 895 - continue; 896 - 897 - if (mc->manual_update && !mc->do_manual_update) 898 - continue; 899 - 900 - if (mgr_busy[oc->channel]) { 901 - busy = true; 902 - continue; 903 - } 904 - 905 - r = configure_overlay(i); 906 - if (r) 907 - DSSERR("configure_overlay %d failed\n", i); 908 - 909 - oc->dirty = false; 910 - oc->shadow_dirty = true; 911 - mgr_go[oc->channel] = true; 912 - } 913 - 914 - /* Commit manager settings */ 915 - for (i = 0; i < num_mgrs; ++i) { 916 - mc = &dss_cache.manager_cache[i]; 917 - 918 - if (!mc->dirty) 919 - continue; 920 - 921 - if (mc->manual_update && !mc->do_manual_update) 922 - continue; 923 - 924 - if (mgr_busy[i]) { 925 - busy = true; 926 - continue; 927 - } 928 - 929 - configure_manager(i); 930 - mc->dirty = false; 931 - mc->shadow_dirty = true; 932 - mgr_go[i] = true; 933 - } 934 - 935 - /* set GO */ 936 - for (i = 0; i < num_mgrs; ++i) { 937 - mc = &dss_cache.manager_cache[i]; 938 - 939 - if (!mgr_go[i]) 940 - continue; 941 - 942 - /* We don't need GO with manual update display. LCD iface will 943 - * always be turned off after frame, and new settings will be 944 - * taken in to use at next update */ 945 - if (!mc->manual_update) 946 - dispc_mgr_go(i); 947 - } 948 - 949 - if (busy) 950 - r = 1; 951 - else 952 - r = 0; 953 - 954 - return r; 955 - } 956 - 957 - /* Make the coordinates even. There are some strange problems with OMAP and 958 - * partial DSI update when the update widths are odd. */ 959 - static void make_even(u16 *x, u16 *w) 960 - { 961 - u16 x1, x2; 962 - 963 - x1 = *x; 964 - x2 = *x + *w; 965 - 966 - x1 &= ~1; 967 - x2 = ALIGN(x2, 2); 968 - 969 - *x = x1; 970 - *w = x2 - x1; 971 - } 972 - 973 - /* Configure dispc for partial update. Return possibly modified update 974 - * area */ 975 - void dss_setup_partial_planes(struct omap_dss_device *dssdev, 976 - u16 *xi, u16 *yi, u16 *wi, u16 *hi, bool enlarge_update_area) 977 - { 978 - struct overlay_cache_data *oc; 979 - struct manager_cache_data *mc; 980 - struct omap_overlay_info *oi; 981 - const int num_ovls = dss_feat_get_num_ovls(); 982 - struct omap_overlay_manager *mgr; 983 - int i; 984 - u16 x, y, w, h; 985 - unsigned long flags; 986 - bool area_changed; 987 - 988 - x = *xi; 989 - y = *yi; 990 - w = *wi; 991 - h = *hi; 992 - 993 - DSSDBG("dispc_setup_partial_planes %d,%d %dx%d\n", 994 - *xi, *yi, *wi, *hi); 995 - 996 - mgr = dssdev->manager; 997 - 998 - if (!mgr) { 999 - DSSDBG("no manager\n"); 1000 - return; 1001 - } 1002 - 1003 - make_even(&x, &w); 1004 - 1005 - spin_lock_irqsave(&dss_cache.lock, flags); 1006 - 1007 - /* 1008 - * Execute the outer loop until the inner loop has completed 1009 - * once without increasing the update area. This will ensure that 1010 - * all scaled overlays end up completely within the update area. 1011 - */ 1012 - do { 1013 - area_changed = false; 1014 - 1015 - /* We need to show the whole overlay if it is scaled. So look 1016 - * for those, and make the update area larger if found. 1017 - * Also mark the overlay cache dirty */ 1018 - for (i = 0; i < num_ovls; ++i) { 1019 - unsigned x1, y1, x2, y2; 1020 - unsigned outw, outh; 1021 - 1022 - oc = &dss_cache.overlay_cache[i]; 1023 - oi = &oc->info; 1024 - 1025 - if (oc->channel != mgr->id) 1026 - continue; 1027 - 1028 - oc->dirty = true; 1029 - 1030 - if (!enlarge_update_area) 1031 - continue; 1032 - 1033 - if (!oc->enabled) 1034 - continue; 1035 - 1036 - if (!dispc_is_overlay_scaled(oc)) 1037 - continue; 1038 - 1039 - outw = oi->out_width == 0 ? 1040 - oi->width : oi->out_width; 1041 - outh = oi->out_height == 0 ? 1042 - oi->height : oi->out_height; 1043 - 1044 - /* is the overlay outside the update region? */ 1045 - if (!rectangle_intersects(x, y, w, h, 1046 - oi->pos_x, oi->pos_y, 1047 - outw, outh)) 1048 - continue; 1049 - 1050 - /* if the overlay totally inside the update region? */ 1051 - if (rectangle_subset(oi->pos_x, oi->pos_y, outw, outh, 1052 - x, y, w, h)) 1053 - continue; 1054 - 1055 - if (x > oi->pos_x) 1056 - x1 = oi->pos_x; 1057 - else 1058 - x1 = x; 1059 - 1060 - if (y > oi->pos_y) 1061 - y1 = oi->pos_y; 1062 - else 1063 - y1 = y; 1064 - 1065 - if ((x + w) < (oi->pos_x + outw)) 1066 - x2 = oi->pos_x + outw; 1067 - else 1068 - x2 = x + w; 1069 - 1070 - if ((y + h) < (oi->pos_y + outh)) 1071 - y2 = oi->pos_y + outh; 1072 - else 1073 - y2 = y + h; 1074 - 1075 - x = x1; 1076 - y = y1; 1077 - w = x2 - x1; 1078 - h = y2 - y1; 1079 - 1080 - make_even(&x, &w); 1081 - 1082 - DSSDBG("changing upd area due to ovl(%d) " 1083 - "scaling %d,%d %dx%d\n", 1084 - i, x, y, w, h); 1085 - 1086 - area_changed = true; 1087 - } 1088 - } while (area_changed); 1089 - 1090 - mc = &dss_cache.manager_cache[mgr->id]; 1091 - mc->do_manual_update = true; 1092 - mc->enlarge_update_area = enlarge_update_area; 1093 - mc->x = x; 1094 - mc->y = y; 1095 - mc->w = w; 1096 - mc->h = h; 1097 - 1098 - configure_dispc(); 1099 - 1100 - mc->do_manual_update = false; 1101 - 1102 - spin_unlock_irqrestore(&dss_cache.lock, flags); 1103 - 1104 - *xi = x; 1105 - *yi = y; 1106 - *wi = w; 1107 - *hi = h; 1108 - } 1109 - 1110 - void dss_start_update(struct omap_dss_device *dssdev) 1111 - { 1112 - struct manager_cache_data *mc; 1113 - struct overlay_cache_data *oc; 1114 - const int num_ovls = dss_feat_get_num_ovls(); 1115 - const int num_mgrs = dss_feat_get_num_mgrs(); 1116 - struct omap_overlay_manager *mgr; 1117 - int i; 1118 - 1119 - mgr = dssdev->manager; 1120 - 1121 - for (i = 0; i < num_ovls; ++i) { 1122 - oc = &dss_cache.overlay_cache[i]; 1123 - if (oc->channel != mgr->id) 1124 - continue; 1125 - 1126 - oc->shadow_dirty = false; 1127 - } 1128 - 1129 - for (i = 0; i < num_mgrs; ++i) { 1130 - mc = &dss_cache.manager_cache[i]; 1131 - if (mgr->id != i) 1132 - continue; 1133 - 1134 - mc->shadow_dirty = false; 1135 - } 1136 - 1137 - dssdev->manager->enable(dssdev->manager); 1138 - } 1139 - 1140 - static void dss_apply_irq_handler(void *data, u32 mask) 1141 - { 1142 - struct manager_cache_data *mc; 1143 - struct overlay_cache_data *oc; 1144 - const int num_ovls = dss_feat_get_num_ovls(); 1145 - const int num_mgrs = dss_feat_get_num_mgrs(); 1146 - int i, r; 1147 - bool mgr_busy[MAX_DSS_MANAGERS]; 1148 - u32 irq_mask; 1149 - 1150 - for (i = 0; i < num_mgrs; i++) 1151 - mgr_busy[i] = dispc_mgr_go_busy(i); 1152 - 1153 - spin_lock(&dss_cache.lock); 1154 - 1155 - for (i = 0; i < num_ovls; ++i) { 1156 - oc = &dss_cache.overlay_cache[i]; 1157 - if (!mgr_busy[oc->channel]) 1158 - oc->shadow_dirty = false; 1159 - } 1160 - 1161 - for (i = 0; i < num_mgrs; ++i) { 1162 - mc = &dss_cache.manager_cache[i]; 1163 - if (!mgr_busy[i]) 1164 - mc->shadow_dirty = false; 1165 - } 1166 - 1167 - r = configure_dispc(); 1168 - if (r == 1) 1169 - goto end; 1170 - 1171 - /* re-read busy flags */ 1172 - for (i = 0; i < num_mgrs; i++) 1173 - mgr_busy[i] = dispc_mgr_go_busy(i); 1174 - 1175 - /* keep running as long as there are busy managers, so that 1176 - * we can collect overlay-applied information */ 1177 - for (i = 0; i < num_mgrs; ++i) { 1178 - if (mgr_busy[i]) 1179 - goto end; 1180 - } 1181 - 1182 - irq_mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD | 1183 - DISPC_IRQ_EVSYNC_EVEN; 1184 - if (dss_has_feature(FEAT_MGR_LCD2)) 1185 - irq_mask |= DISPC_IRQ_VSYNC2; 1186 - 1187 - omap_dispc_unregister_isr(dss_apply_irq_handler, NULL, irq_mask); 1188 - dss_cache.irq_enabled = false; 1189 - 1190 - end: 1191 - spin_unlock(&dss_cache.lock); 1192 - } 1193 - 1194 - static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr) 1195 - { 1196 - struct overlay_cache_data *oc; 1197 - struct manager_cache_data *mc; 1198 - int i; 1199 - struct omap_overlay *ovl; 1200 - int num_planes_enabled = 0; 1201 - bool use_fifomerge; 1202 - unsigned long flags; 1203 - int r; 1204 - 1205 - DSSDBG("omap_dss_mgr_apply(%s)\n", mgr->name); 1206 - 1207 - r = dispc_runtime_get(); 1208 - if (r) 1209 - return r; 1210 - 1211 - spin_lock_irqsave(&dss_cache.lock, flags); 1212 - 1213 - /* Configure overlays */ 1214 - for (i = 0; i < omap_dss_get_num_overlays(); ++i) { 1215 - struct omap_dss_device *dssdev; 1216 - 1217 - ovl = omap_dss_get_overlay(i); 1218 - 1219 - oc = &dss_cache.overlay_cache[ovl->id]; 1220 - 1221 - if (ovl->manager_changed) { 1222 - ovl->manager_changed = false; 1223 - ovl->info_dirty = true; 1224 - } 1225 - 1226 - if (!overlay_enabled(ovl)) { 1227 - if (oc->enabled) { 1228 - oc->enabled = false; 1229 - oc->dirty = true; 1230 - } 1231 - continue; 1232 - } 1233 - 1234 - if (!ovl->info_dirty) { 1235 - if (oc->enabled) 1236 - ++num_planes_enabled; 1237 - continue; 1238 - } 1239 - 1240 - dssdev = ovl->manager->device; 1241 - 1242 - if (dss_check_overlay(ovl, dssdev)) { 1243 - if (oc->enabled) { 1244 - oc->enabled = false; 1245 - oc->dirty = true; 1246 - } 1247 - continue; 1248 - } 1249 - 1250 - ovl->info_dirty = false; 1251 - oc->dirty = true; 1252 - oc->info = ovl->info; 1253 - 1254 - oc->replication = 1255 - dss_use_replication(dssdev, ovl->info.color_mode); 1256 - 1257 - oc->ilace = dssdev->type == OMAP_DISPLAY_TYPE_VENC; 1258 - 1259 - oc->channel = ovl->manager->id; 1260 - 1261 - oc->enabled = true; 1262 - 1263 - ++num_planes_enabled; 1264 - } 1265 - 1266 - /* Configure managers */ 1267 - list_for_each_entry(mgr, &manager_list, list) { 1268 - struct omap_dss_device *dssdev; 1269 - 1270 - mc = &dss_cache.manager_cache[mgr->id]; 1271 - 1272 - if (mgr->device_changed) { 1273 - mgr->device_changed = false; 1274 - mgr->info_dirty = true; 1275 - } 1276 - 1277 - if (!mgr->info_dirty) 1278 - continue; 1279 - 1280 - if (!mgr->device) 1281 - continue; 1282 - 1283 - dssdev = mgr->device; 1284 - 1285 - mgr->info_dirty = false; 1286 - mc->dirty = true; 1287 - mc->info = mgr->info; 1288 - 1289 - mc->manual_update = 1290 - dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; 1291 - } 1292 - 1293 - /* XXX TODO: Try to get fifomerge working. The problem is that it 1294 - * affects both managers, not individually but at the same time. This 1295 - * means the change has to be well synchronized. I guess the proper way 1296 - * is to have a two step process for fifo merge: 1297 - * fifomerge enable: 1298 - * 1. disable other planes, leaving one plane enabled 1299 - * 2. wait until the planes are disabled on HW 1300 - * 3. config merged fifo thresholds, enable fifomerge 1301 - * fifomerge disable: 1302 - * 1. config unmerged fifo thresholds, disable fifomerge 1303 - * 2. wait until fifo changes are in HW 1304 - * 3. enable planes 1305 - */ 1306 - use_fifomerge = false; 1307 - 1308 - /* Configure overlay fifos */ 1309 - for (i = 0; i < omap_dss_get_num_overlays(); ++i) { 1310 - struct omap_dss_device *dssdev; 1311 - u32 size, burst_size; 1312 - 1313 - ovl = omap_dss_get_overlay(i); 1314 - 1315 - oc = &dss_cache.overlay_cache[ovl->id]; 1316 - 1317 - if (!oc->enabled) 1318 - continue; 1319 - 1320 - dssdev = ovl->manager->device; 1321 - 1322 - size = dispc_ovl_get_fifo_size(ovl->id); 1323 - if (use_fifomerge) 1324 - size *= 3; 1325 - 1326 - burst_size = dispc_ovl_get_burst_size(ovl->id); 1327 - 1328 - switch (dssdev->type) { 1329 - case OMAP_DISPLAY_TYPE_DPI: 1330 - case OMAP_DISPLAY_TYPE_DBI: 1331 - case OMAP_DISPLAY_TYPE_SDI: 1332 - case OMAP_DISPLAY_TYPE_VENC: 1333 - case OMAP_DISPLAY_TYPE_HDMI: 1334 - default_get_overlay_fifo_thresholds(ovl->id, size, 1335 - burst_size, &oc->fifo_low, 1336 - &oc->fifo_high); 1337 - break; 1338 - #ifdef CONFIG_OMAP2_DSS_DSI 1339 - case OMAP_DISPLAY_TYPE_DSI: 1340 - dsi_get_overlay_fifo_thresholds(ovl->id, size, 1341 - burst_size, &oc->fifo_low, 1342 - &oc->fifo_high); 1343 - break; 1344 - #endif 1345 - default: 1346 - BUG(); 1347 - } 1348 - } 1349 - 1350 - r = 0; 1351 - if (!dss_cache.irq_enabled) { 1352 - u32 mask; 1353 - 1354 - mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_ODD | 1355 - DISPC_IRQ_EVSYNC_EVEN; 1356 - if (dss_has_feature(FEAT_MGR_LCD2)) 1357 - mask |= DISPC_IRQ_VSYNC2; 1358 - 1359 - r = omap_dispc_register_isr(dss_apply_irq_handler, NULL, mask); 1360 - dss_cache.irq_enabled = true; 1361 - } 1362 - configure_dispc(); 1363 - 1364 - spin_unlock_irqrestore(&dss_cache.lock, flags); 1365 - 1366 - dispc_runtime_put(); 1367 - 1368 - return r; 1369 - } 1370 - 1371 - static int dss_check_manager(struct omap_overlay_manager *mgr) 1372 - { 1373 - if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) { 1374 - /* 1375 - * OMAP3 supports only graphics source transparency color key 1376 - * and alpha blending simultaneously. See TRM 15.4.2.4.2.2 1377 - * Alpha Mode 1378 - */ 1379 - if (mgr->info.partial_alpha_enabled && mgr->info.trans_enabled 1380 - && mgr->info.trans_key_type != 1381 - OMAP_DSS_COLOR_KEY_GFX_DST) 1382 - return -EINVAL; 1383 - } 1384 - 1385 - return 0; 1386 - } 1387 - 1388 - static int omap_dss_mgr_set_info(struct omap_overlay_manager *mgr, 1389 - struct omap_overlay_manager_info *info) 1390 - { 1391 - int r; 1392 - struct omap_overlay_manager_info old_info; 1393 - 1394 - old_info = mgr->info; 1395 - mgr->info = *info; 1396 - 1397 - r = dss_check_manager(mgr); 1398 - if (r) { 1399 - mgr->info = old_info; 1400 - return r; 1401 - } 1402 - 1403 - mgr->info_dirty = true; 1404 - 1405 - return 0; 1406 - } 1407 - 1408 - static void omap_dss_mgr_get_info(struct omap_overlay_manager *mgr, 1409 - struct omap_overlay_manager_info *info) 1410 - { 1411 - *info = mgr->info; 1412 - } 1413 - 1414 - static int dss_mgr_enable(struct omap_overlay_manager *mgr) 1415 - { 1416 - dispc_mgr_enable(mgr->id, 1); 1417 - return 0; 1418 - } 1419 - 1420 - static int dss_mgr_disable(struct omap_overlay_manager *mgr) 1421 - { 1422 - dispc_mgr_enable(mgr->id, 0); 1423 - return 0; 1424 - } 1425 - 1426 - static void omap_dss_add_overlay_manager(struct omap_overlay_manager *manager) 1427 - { 1428 - ++num_managers; 1429 - list_add_tail(&manager->list, &manager_list); 1430 - } 1431 - 1432 627 int dss_init_overlay_managers(struct platform_device *pdev) 1433 628 { 1434 629 int i, r; 1435 630 1436 - spin_lock_init(&dss_cache.lock); 631 + num_managers = dss_feat_get_num_mgrs(); 1437 632 1438 - INIT_LIST_HEAD(&manager_list); 633 + managers = kzalloc(sizeof(struct omap_overlay_manager) * num_managers, 634 + GFP_KERNEL); 1439 635 1440 - num_managers = 0; 636 + BUG_ON(managers == NULL); 1441 637 1442 - for (i = 0; i < dss_feat_get_num_mgrs(); ++i) { 1443 - struct omap_overlay_manager *mgr; 1444 - mgr = kzalloc(sizeof(*mgr), GFP_KERNEL); 1445 - 1446 - BUG_ON(mgr == NULL); 638 + for (i = 0; i < num_managers; ++i) { 639 + struct omap_overlay_manager *mgr = &managers[i]; 1447 640 1448 641 switch (i) { 1449 642 case 0: ··· 537 1576 break; 538 1577 } 539 1578 540 - mgr->set_device = &omap_dss_set_device; 541 - mgr->unset_device = &omap_dss_unset_device; 1579 + mgr->set_device = &dss_mgr_set_device; 1580 + mgr->unset_device = &dss_mgr_unset_device; 542 1581 mgr->apply = &omap_dss_mgr_apply; 543 - mgr->set_manager_info = &omap_dss_mgr_set_info; 544 - mgr->get_manager_info = &omap_dss_mgr_get_info; 1582 + mgr->set_manager_info = &dss_mgr_set_info; 1583 + mgr->get_manager_info = &dss_mgr_get_info; 545 1584 mgr->wait_for_go = &dss_mgr_wait_for_go; 546 1585 mgr->wait_for_vsync = &dss_mgr_wait_for_vsync; 547 - 548 - mgr->enable = &dss_mgr_enable; 549 - mgr->disable = &dss_mgr_disable; 550 1586 551 1587 mgr->caps = 0; 552 1588 mgr->supported_displays = 553 1589 dss_feat_get_supported_displays(mgr->id); 554 1590 555 - dss_overlay_setup_dispc_manager(mgr); 556 - 557 - omap_dss_add_overlay_manager(mgr); 1591 + INIT_LIST_HEAD(&mgr->overlays); 558 1592 559 1593 r = kobject_init_and_add(&mgr->kobj, &manager_ktype, 560 1594 &pdev->dev.kobj, "manager%d", i); 561 1595 562 - if (r) { 1596 + if (r) 563 1597 DSSERR("failed to create sysfs file\n"); 564 - continue; 565 - } 566 1598 } 567 1599 568 1600 return 0; ··· 563 1609 564 1610 void dss_uninit_overlay_managers(struct platform_device *pdev) 565 1611 { 566 - struct omap_overlay_manager *mgr; 1612 + int i; 567 1613 568 - while (!list_empty(&manager_list)) { 569 - mgr = list_first_entry(&manager_list, 570 - struct omap_overlay_manager, list); 571 - list_del(&mgr->list); 1614 + for (i = 0; i < num_managers; ++i) { 1615 + struct omap_overlay_manager *mgr = &managers[i]; 1616 + 572 1617 kobject_del(&mgr->kobj); 573 1618 kobject_put(&mgr->kobj); 574 - kfree(mgr); 575 1619 } 576 1620 1621 + kfree(managers); 1622 + managers = NULL; 577 1623 num_managers = 0; 578 1624 } 579 1625 ··· 585 1631 586 1632 struct omap_overlay_manager *omap_dss_get_overlay_manager(int num) 587 1633 { 588 - int i = 0; 589 - struct omap_overlay_manager *mgr; 1634 + if (num >= num_managers) 1635 + return NULL; 590 1636 591 - list_for_each_entry(mgr, &manager_list, list) { 592 - if (i++ == num) 593 - return mgr; 594 - } 595 - 596 - return NULL; 1637 + return &managers[num]; 597 1638 } 598 1639 EXPORT_SYMBOL(omap_dss_get_overlay_manager); 599 1640 1641 + int dss_mgr_simple_check(struct omap_overlay_manager *mgr, 1642 + const struct omap_overlay_manager_info *info) 1643 + { 1644 + if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) { 1645 + /* 1646 + * OMAP3 supports only graphics source transparency color key 1647 + * and alpha blending simultaneously. See TRM 15.4.2.4.2.2 1648 + * Alpha Mode. 1649 + */ 1650 + if (info->partial_alpha_enabled && info->trans_enabled 1651 + && info->trans_key_type != OMAP_DSS_COLOR_KEY_GFX_DST) { 1652 + DSSERR("check_manager: illegal transparency key\n"); 1653 + return -EINVAL; 1654 + } 1655 + } 1656 + 1657 + return 0; 1658 + } 1659 + 1660 + static int dss_mgr_check_zorder(struct omap_overlay_manager *mgr, 1661 + struct omap_overlay_info **overlay_infos) 1662 + { 1663 + struct omap_overlay *ovl1, *ovl2; 1664 + struct omap_overlay_info *info1, *info2; 1665 + 1666 + list_for_each_entry(ovl1, &mgr->overlays, list) { 1667 + info1 = overlay_infos[ovl1->id]; 1668 + 1669 + if (info1 == NULL) 1670 + continue; 1671 + 1672 + list_for_each_entry(ovl2, &mgr->overlays, list) { 1673 + if (ovl1 == ovl2) 1674 + continue; 1675 + 1676 + info2 = overlay_infos[ovl2->id]; 1677 + 1678 + if (info2 == NULL) 1679 + continue; 1680 + 1681 + if (info1->zorder == info2->zorder) { 1682 + DSSERR("overlays %d and %d have the same " 1683 + "zorder %d\n", 1684 + ovl1->id, ovl2->id, info1->zorder); 1685 + return -EINVAL; 1686 + } 1687 + } 1688 + } 1689 + 1690 + return 0; 1691 + } 1692 + 1693 + int dss_mgr_check(struct omap_overlay_manager *mgr, 1694 + struct omap_dss_device *dssdev, 1695 + struct omap_overlay_manager_info *info, 1696 + struct omap_overlay_info **overlay_infos) 1697 + { 1698 + struct omap_overlay *ovl; 1699 + int r; 1700 + 1701 + if (dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) { 1702 + r = dss_mgr_check_zorder(mgr, overlay_infos); 1703 + if (r) 1704 + return r; 1705 + } 1706 + 1707 + list_for_each_entry(ovl, &mgr->overlays, list) { 1708 + struct omap_overlay_info *oi; 1709 + int r; 1710 + 1711 + oi = overlay_infos[ovl->id]; 1712 + 1713 + if (oi == NULL) 1714 + continue; 1715 + 1716 + r = dss_ovl_check(ovl, oi, dssdev); 1717 + if (r) 1718 + return r; 1719 + } 1720 + 1721 + return 0; 1722 + }
+144 -291
drivers/video/omap2/dss/overlay.c
··· 38 38 #include "dss_features.h" 39 39 40 40 static int num_overlays; 41 - static struct list_head overlay_list; 41 + static struct omap_overlay *overlays; 42 42 43 43 static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf) 44 44 { ··· 124 124 125 125 static 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 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 131 135 static 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 136 144 static 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 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 142 154 static ssize_t overlay_position_store(struct omap_overlay *ovl, ··· 182 170 183 171 static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf) 184 172 { 173 + struct omap_overlay_info info; 174 + 175 + ovl->get_overlay_info(ovl, &info); 176 + 185 177 return snprintf(buf, PAGE_SIZE, "%d,%d\n", 186 - ovl->info.out_width, ovl->info.out_height); 178 + info.out_width, info.out_height); 187 179 } 188 180 189 181 static ssize_t overlay_output_size_store(struct omap_overlay *ovl, ··· 221 205 222 206 static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf) 223 207 { 224 - return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.enabled); 208 + return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl)); 225 209 } 226 210 227 211 static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf, ··· 229 213 { 230 214 int r; 231 215 bool enable; 232 - struct omap_overlay_info info; 233 - 234 - ovl->get_overlay_info(ovl, &info); 235 216 236 217 r = strtobool(buf, &enable); 237 218 if (r) 238 219 return r; 239 220 240 - info.enabled = enable; 221 + if (enable) 222 + r = ovl->enable(ovl); 223 + else 224 + r = ovl->disable(ovl); 241 225 242 - r = ovl->set_overlay_info(ovl, &info); 243 226 if (r) 244 227 return r; 245 - 246 - if (ovl->manager) { 247 - r = ovl->manager->apply(ovl->manager); 248 - if (r) 249 - return r; 250 - } 251 228 252 229 return size; 253 230 } 254 231 255 232 static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf) 256 233 { 234 + struct omap_overlay_info info; 235 + 236 + ovl->get_overlay_info(ovl, &info); 237 + 257 238 return snprintf(buf, PAGE_SIZE, "%d\n", 258 - ovl->info.global_alpha); 239 + info.global_alpha); 259 240 } 260 241 261 242 static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl, ··· 289 276 static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl, 290 277 char *buf) 291 278 { 279 + struct omap_overlay_info info; 280 + 281 + ovl->get_overlay_info(ovl, &info); 282 + 292 283 return snprintf(buf, PAGE_SIZE, "%d\n", 293 - ovl->info.pre_mult_alpha); 284 + info.pre_mult_alpha); 294 285 } 295 286 296 287 static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl, ··· 330 313 331 314 static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf) 332 315 { 333 - return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.zorder); 316 + struct omap_overlay_info info; 317 + 318 + ovl->get_overlay_info(ovl, &info); 319 + 320 + return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder); 334 321 } 335 322 336 323 static ssize_t overlay_zorder_store(struct omap_overlay *ovl, ··· 451 430 .default_attrs = overlay_sysfs_attrs, 452 431 }; 453 432 454 - /* Check if overlay parameters are compatible with display */ 455 - int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev) 456 - { 457 - struct omap_overlay_info *info; 458 - u16 outw, outh; 459 - u16 dw, dh; 460 - int i; 461 - 462 - if (!dssdev) 463 - return 0; 464 - 465 - if (!ovl->info.enabled) 466 - return 0; 467 - 468 - info = &ovl->info; 469 - 470 - if (info->paddr == 0) { 471 - DSSDBG("check_overlay failed: paddr 0\n"); 472 - return -EINVAL; 473 - } 474 - 475 - dssdev->driver->get_resolution(dssdev, &dw, &dh); 476 - 477 - DSSDBG("check_overlay %d: (%d,%d %dx%d -> %dx%d) disp (%dx%d)\n", 478 - ovl->id, 479 - info->pos_x, info->pos_y, 480 - info->width, info->height, 481 - info->out_width, info->out_height, 482 - dw, dh); 483 - 484 - if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { 485 - outw = info->width; 486 - outh = info->height; 487 - } else { 488 - if (info->out_width == 0) 489 - outw = info->width; 490 - else 491 - outw = info->out_width; 492 - 493 - if (info->out_height == 0) 494 - outh = info->height; 495 - else 496 - outh = info->out_height; 497 - } 498 - 499 - if (dw < info->pos_x + outw) { 500 - DSSDBG("check_overlay failed 1: %d < %d + %d\n", 501 - dw, info->pos_x, outw); 502 - return -EINVAL; 503 - } 504 - 505 - if (dh < info->pos_y + outh) { 506 - DSSDBG("check_overlay failed 2: %d < %d + %d\n", 507 - dh, info->pos_y, outh); 508 - return -EINVAL; 509 - } 510 - 511 - if ((ovl->supported_modes & info->color_mode) == 0) { 512 - DSSERR("overlay doesn't support mode %d\n", info->color_mode); 513 - return -EINVAL; 514 - } 515 - 516 - if (ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) { 517 - if (info->zorder < 0 || info->zorder > 3) { 518 - DSSERR("zorder out of range: %d\n", 519 - info->zorder); 520 - return -EINVAL; 521 - } 522 - /* 523 - * Check that zorder doesn't match with zorder of any other 524 - * overlay which is enabled and is also connected to the same 525 - * manager 526 - */ 527 - for (i = 0; i < omap_dss_get_num_overlays(); i++) { 528 - struct omap_overlay *tmp_ovl = omap_dss_get_overlay(i); 529 - 530 - if (tmp_ovl->id != ovl->id && 531 - tmp_ovl->manager == ovl->manager && 532 - tmp_ovl->info.enabled == true && 533 - tmp_ovl->info.zorder == info->zorder) { 534 - DSSERR("%s and %s have same zorder: %d\n", 535 - ovl->name, tmp_ovl->name, info->zorder); 536 - return -EINVAL; 537 - } 538 - } 539 - } 540 - 541 - return 0; 542 - } 543 - 544 - static int dss_ovl_set_overlay_info(struct omap_overlay *ovl, 545 - struct omap_overlay_info *info) 546 - { 547 - int r; 548 - struct omap_overlay_info old_info; 549 - 550 - old_info = ovl->info; 551 - ovl->info = *info; 552 - 553 - if (ovl->manager) { 554 - r = dss_check_overlay(ovl, ovl->manager->device); 555 - if (r) { 556 - ovl->info = old_info; 557 - return r; 558 - } 559 - } 560 - 561 - ovl->info_dirty = true; 562 - 563 - return 0; 564 - } 565 - 566 - static void dss_ovl_get_overlay_info(struct omap_overlay *ovl, 567 - struct omap_overlay_info *info) 568 - { 569 - *info = ovl->info; 570 - } 571 - 572 - static int dss_ovl_wait_for_go(struct omap_overlay *ovl) 573 - { 574 - return dss_mgr_wait_for_go_ovl(ovl); 575 - } 576 - 577 - static int omap_dss_set_manager(struct omap_overlay *ovl, 578 - struct omap_overlay_manager *mgr) 579 - { 580 - if (!mgr) 581 - return -EINVAL; 582 - 583 - if (ovl->manager) { 584 - DSSERR("overlay '%s' already has a manager '%s'\n", 585 - ovl->name, ovl->manager->name); 586 - return -EINVAL; 587 - } 588 - 589 - if (ovl->info.enabled) { 590 - DSSERR("overlay has to be disabled to change the manager\n"); 591 - return -EINVAL; 592 - } 593 - 594 - ovl->manager = mgr; 595 - ovl->manager_changed = true; 596 - 597 - /* XXX: When there is an overlay on a DSI manual update display, and 598 - * the overlay is first disabled, then moved to tv, and enabled, we 599 - * seem to get SYNC_LOST_DIGIT error. 600 - * 601 - * Waiting doesn't seem to help, but updating the manual update display 602 - * after disabling the overlay seems to fix this. This hints that the 603 - * overlay is perhaps somehow tied to the LCD output until the output 604 - * is updated. 605 - * 606 - * Userspace workaround for this is to update the LCD after disabling 607 - * the overlay, but before moving the overlay to TV. 608 - */ 609 - 610 - return 0; 611 - } 612 - 613 - static int omap_dss_unset_manager(struct omap_overlay *ovl) 614 - { 615 - if (!ovl->manager) { 616 - DSSERR("failed to detach overlay: manager not set\n"); 617 - return -EINVAL; 618 - } 619 - 620 - if (ovl->info.enabled) { 621 - DSSERR("overlay has to be disabled to unset the manager\n"); 622 - return -EINVAL; 623 - } 624 - 625 - ovl->manager = NULL; 626 - ovl->manager_changed = true; 627 - 628 - return 0; 629 - } 630 - 631 433 int omap_dss_get_num_overlays(void) 632 434 { 633 435 return num_overlays; ··· 459 615 460 616 struct omap_overlay *omap_dss_get_overlay(int num) 461 617 { 462 - int i = 0; 463 - struct omap_overlay *ovl; 618 + if (num >= num_overlays) 619 + return NULL; 464 620 465 - list_for_each_entry(ovl, &overlay_list, list) { 466 - if (i++ == num) 467 - return ovl; 468 - } 469 - 470 - return NULL; 621 + return &overlays[num]; 471 622 } 472 623 EXPORT_SYMBOL(omap_dss_get_overlay); 473 - 474 - static void omap_dss_add_overlay(struct omap_overlay *overlay) 475 - { 476 - ++num_overlays; 477 - list_add_tail(&overlay->list, &overlay_list); 478 - } 479 - 480 - static struct omap_overlay *dispc_overlays[MAX_DSS_OVERLAYS]; 481 - 482 - void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr) 483 - { 484 - mgr->num_overlays = dss_feat_get_num_ovls(); 485 - mgr->overlays = dispc_overlays; 486 - } 487 - 488 - #ifdef L4_EXAMPLE 489 - static struct omap_overlay *l4_overlays[1]; 490 - void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr) 491 - { 492 - mgr->num_overlays = 1; 493 - mgr->overlays = l4_overlays; 494 - } 495 - #endif 496 624 497 625 void dss_init_overlays(struct platform_device *pdev) 498 626 { 499 627 int i, r; 500 628 501 - INIT_LIST_HEAD(&overlay_list); 629 + num_overlays = dss_feat_get_num_ovls(); 502 630 503 - num_overlays = 0; 631 + overlays = kzalloc(sizeof(struct omap_overlay) * num_overlays, 632 + GFP_KERNEL); 504 633 505 - for (i = 0; i < dss_feat_get_num_ovls(); ++i) { 506 - struct omap_overlay *ovl; 507 - ovl = kzalloc(sizeof(*ovl), GFP_KERNEL); 634 + BUG_ON(overlays == NULL); 508 635 509 - BUG_ON(ovl == NULL); 636 + for (i = 0; i < num_overlays; ++i) { 637 + struct omap_overlay *ovl = &overlays[i]; 510 638 511 639 switch (i) { 512 640 case 0: 513 641 ovl->name = "gfx"; 514 642 ovl->id = OMAP_DSS_GFX; 515 - ovl->info.global_alpha = 255; 516 - ovl->info.zorder = 0; 517 643 break; 518 644 case 1: 519 645 ovl->name = "vid1"; 520 646 ovl->id = OMAP_DSS_VIDEO1; 521 - ovl->info.global_alpha = 255; 522 - ovl->info.zorder = 523 - dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0; 524 647 break; 525 648 case 2: 526 649 ovl->name = "vid2"; 527 650 ovl->id = OMAP_DSS_VIDEO2; 528 - ovl->info.global_alpha = 255; 529 - ovl->info.zorder = 530 - dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0; 531 651 break; 532 652 case 3: 533 653 ovl->name = "vid3"; 534 654 ovl->id = OMAP_DSS_VIDEO3; 535 - ovl->info.global_alpha = 255; 536 - ovl->info.zorder = 537 - dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0; 538 655 break; 539 656 } 540 657 541 - ovl->set_manager = &omap_dss_set_manager; 542 - ovl->unset_manager = &omap_dss_unset_manager; 543 - ovl->set_overlay_info = &dss_ovl_set_overlay_info; 544 - ovl->get_overlay_info = &dss_ovl_get_overlay_info; 545 - ovl->wait_for_go = &dss_ovl_wait_for_go; 658 + ovl->is_enabled = &dss_ovl_is_enabled; 659 + ovl->enable = &dss_ovl_enable; 660 + ovl->disable = &dss_ovl_disable; 661 + ovl->set_manager = &dss_ovl_set_manager; 662 + ovl->unset_manager = &dss_ovl_unset_manager; 663 + ovl->set_overlay_info = &dss_ovl_set_info; 664 + ovl->get_overlay_info = &dss_ovl_get_info; 665 + ovl->wait_for_go = &dss_mgr_wait_for_go_ovl; 546 666 547 667 ovl->caps = dss_feat_get_overlay_caps(ovl->id); 548 668 ovl->supported_modes = 549 669 dss_feat_get_supported_color_modes(ovl->id); 550 670 551 - omap_dss_add_overlay(ovl); 552 - 553 671 r = kobject_init_and_add(&ovl->kobj, &overlay_ktype, 554 672 &pdev->dev.kobj, "overlay%d", i); 555 673 556 - if (r) { 557 - DSSERR("failed to create sysfs file\n"); 558 - continue; 559 - } 560 - 561 - dispc_overlays[i] = ovl; 562 - } 563 - 564 - #ifdef L4_EXAMPLE 565 - { 566 - struct omap_overlay *ovl; 567 - ovl = kzalloc(sizeof(*ovl), GFP_KERNEL); 568 - 569 - BUG_ON(ovl == NULL); 570 - 571 - ovl->name = "l4"; 572 - ovl->supported_modes = OMAP_DSS_COLOR_RGB24U; 573 - 574 - ovl->set_manager = &omap_dss_set_manager; 575 - ovl->unset_manager = &omap_dss_unset_manager; 576 - ovl->set_overlay_info = &dss_ovl_set_overlay_info; 577 - ovl->get_overlay_info = &dss_ovl_get_overlay_info; 578 - 579 - omap_dss_add_overlay(ovl); 580 - 581 - r = kobject_init_and_add(&ovl->kobj, &overlay_ktype, 582 - &pdev->dev.kobj, "overlayl4"); 583 - 584 674 if (r) 585 675 DSSERR("failed to create sysfs file\n"); 586 - 587 - l4_overlays[0] = ovl; 588 676 } 589 - #endif 590 677 } 591 678 592 679 /* connect overlays to the new device, if not already connected. if force ··· 570 795 ovl = omap_dss_get_overlay(i); 571 796 if (!ovl->manager || force) { 572 797 if (ovl->manager) 573 - omap_dss_unset_manager(ovl); 574 - omap_dss_set_manager(ovl, mgr); 798 + ovl->unset_manager(ovl); 799 + ovl->set_manager(ovl, mgr); 575 800 } 576 801 } 577 802 ··· 581 806 582 807 void dss_uninit_overlays(struct platform_device *pdev) 583 808 { 584 - struct omap_overlay *ovl; 809 + int i; 585 810 586 - while (!list_empty(&overlay_list)) { 587 - ovl = list_first_entry(&overlay_list, 588 - struct omap_overlay, list); 589 - list_del(&ovl->list); 811 + for (i = 0; i < num_overlays; ++i) { 812 + struct omap_overlay *ovl = &overlays[i]; 813 + 590 814 kobject_del(&ovl->kobj); 591 815 kobject_put(&ovl->kobj); 592 - kfree(ovl); 593 816 } 594 817 818 + kfree(overlays); 819 + overlays = NULL; 595 820 num_overlays = 0; 596 821 } 597 822 823 + int dss_ovl_simple_check(struct omap_overlay *ovl, 824 + const struct omap_overlay_info *info) 825 + { 826 + if (info->paddr == 0) { 827 + DSSERR("check_overlay: paddr cannot be 0\n"); 828 + return -EINVAL; 829 + } 830 + 831 + if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { 832 + if (info->out_width != 0 && info->width != info->out_width) { 833 + DSSERR("check_overlay: overlay %d doesn't support " 834 + "scaling\n", ovl->id); 835 + return -EINVAL; 836 + } 837 + 838 + if (info->out_height != 0 && info->height != info->out_height) { 839 + DSSERR("check_overlay: overlay %d doesn't support " 840 + "scaling\n", ovl->id); 841 + return -EINVAL; 842 + } 843 + } 844 + 845 + if ((ovl->supported_modes & info->color_mode) == 0) { 846 + DSSERR("check_overlay: overlay %d doesn't support mode %d\n", 847 + ovl->id, info->color_mode); 848 + return -EINVAL; 849 + } 850 + 851 + if (info->zorder >= omap_dss_get_num_overlays()) { 852 + DSSERR("check_overlay: zorder %d too high\n", info->zorder); 853 + return -EINVAL; 854 + } 855 + 856 + return 0; 857 + } 858 + 859 + int dss_ovl_check(struct omap_overlay *ovl, 860 + struct omap_overlay_info *info, struct omap_dss_device *dssdev) 861 + { 862 + u16 outw, outh; 863 + u16 dw, dh; 864 + 865 + if (dssdev == NULL) 866 + return 0; 867 + 868 + dssdev->driver->get_resolution(dssdev, &dw, &dh); 869 + 870 + if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) { 871 + outw = info->width; 872 + outh = info->height; 873 + } else { 874 + if (info->out_width == 0) 875 + outw = info->width; 876 + else 877 + outw = info->out_width; 878 + 879 + if (info->out_height == 0) 880 + outh = info->height; 881 + else 882 + outh = info->out_height; 883 + } 884 + 885 + if (dw < info->pos_x + outw) { 886 + DSSERR("overlay %d horizontally not inside the display area " 887 + "(%d + %d >= %d)\n", 888 + ovl->id, info->pos_x, outw, dw); 889 + return -EINVAL; 890 + } 891 + 892 + if (dh < info->pos_y + outh) { 893 + DSSERR("overlay %d vertically not inside the display area " 894 + "(%d + %d >= %d)\n", 895 + ovl->id, info->pos_y, outh, dh); 896 + return -EINVAL; 897 + } 898 + 899 + return 0; 900 + }
-1
drivers/video/omap2/dss/rfbi.c
··· 784 784 if (*w == 0 || *h == 0) 785 785 return -EINVAL; 786 786 787 - dss_setup_partial_planes(dssdev, x, y, w, h, true); 788 787 dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h); 789 788 790 789 return 0;
+6 -2
drivers/video/omap2/dss/sdi.c
··· 123 123 goto err_sdi_enable; 124 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 130 return 0; 129 131 132 + err_mgr_enable: 133 + dss_sdi_disable(); 130 134 err_sdi_enable: 131 135 err_set_dispc_clock_div: 132 136 err_set_dss_clock_div: ··· 149 145 150 146 void omapdss_sdi_display_disable(struct omap_dss_device *dssdev) 151 147 { 152 - dssdev->manager->disable(dssdev->manager); 148 + dss_mgr_disable(dssdev->manager); 153 149 154 150 dss_sdi_disable(); 155 151
+9 -1
drivers/video/omap2/dss/ti_hdmi.h
··· 110 110 111 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 115 120 struct hdmi_ip_data { ··· 139 134 void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); 140 135 void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); 141 136 void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s); 142 - 137 + #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ 138 + defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) 139 + void ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data, bool enable); 140 + #endif 143 141 #endif
+7 -30
drivers/video/omap2/dss/ti_hdmi_4xxx_ip.c
··· 1204 1204 return 0; 1205 1205 } 1206 1206 1207 - int hdmi_audio_trigger(struct hdmi_ip_data *ip_data, 1208 - struct snd_pcm_substream *substream, int cmd, 1209 - struct snd_soc_dai *dai) 1207 + void ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data, bool enable) 1210 1208 { 1211 - int err = 0; 1212 - switch (cmd) { 1213 - case SNDRV_PCM_TRIGGER_START: 1214 - case SNDRV_PCM_TRIGGER_RESUME: 1215 - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 1216 - REG_FLD_MOD(hdmi_av_base(ip_data), 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; 1209 + REG_FLD_MOD(hdmi_av_base(ip_data), 1210 + HDMI_CORE_AV_AUD_MODE, enable, 0, 0); 1211 + REG_FLD_MOD(hdmi_wp_base(ip_data), 1212 + HDMI_WP_AUDIO_CTRL, enable, 31, 31); 1213 + REG_FLD_MOD(hdmi_wp_base(ip_data), 1214 + HDMI_WP_AUDIO_CTRL, enable, 30, 30); 1238 1215 } 1239 1216 #endif
-3
drivers/video/omap2/dss/ti_hdmi_4xxx_ip.h
··· 576 576 577 577 #if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \ 578 578 defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE) 579 - int hdmi_audio_trigger(struct hdmi_ip_data *ip_data, 580 - struct snd_pcm_substream *substream, int cmd, 581 - struct snd_soc_dai *dai); 582 579 int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data, 583 580 u32 sample_freq, u32 *n, u32 *cts); 584 581 void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
+24 -4
drivers/video/omap2/dss/venc.c
··· 417 417 BUG(); 418 418 } 419 419 420 - static void venc_power_on(struct omap_dss_device *dssdev) 420 + static int venc_power_on(struct omap_dss_device *dssdev) 421 421 { 422 422 u32 l; 423 + int r; 423 424 424 425 venc_reset(); 425 426 venc_write_config(venc_timings_to_config(&dssdev->panel.timings)); ··· 448 447 if (dssdev->platform_enable) 449 448 dssdev->platform_enable(dssdev); 450 449 451 - dssdev->manager->enable(dssdev->manager); 450 + r = dss_mgr_enable(dssdev->manager); 451 + if (r) 452 + goto err; 453 + 454 + return 0; 455 + 456 + err: 457 + venc_write_reg(VENC_OUTPUT_CONTROL, 0); 458 + dss_set_dac_pwrdn_bgz(0); 459 + 460 + if (dssdev->platform_disable) 461 + dssdev->platform_disable(dssdev); 462 + 463 + regulator_disable(venc.vdda_dac_reg); 464 + 465 + return r; 452 466 } 453 467 454 468 static void venc_power_off(struct omap_dss_device *dssdev) ··· 471 455 venc_write_reg(VENC_OUTPUT_CONTROL, 0); 472 456 dss_set_dac_pwrdn_bgz(0); 473 457 474 - dssdev->manager->disable(dssdev->manager); 458 + dss_mgr_disable(dssdev->manager); 475 459 476 460 if (dssdev->platform_disable) 477 461 dssdev->platform_disable(dssdev); ··· 520 504 if (r) 521 505 goto err1; 522 506 523 - venc_power_on(dssdev); 507 + r = venc_power_on(dssdev); 508 + if (r) 509 + goto err2; 524 510 525 511 venc.wss_data = 0; 526 512 ··· 530 512 531 513 mutex_unlock(&venc.venc_lock); 532 514 return 0; 515 + err2: 516 + venc_runtime_put(); 533 517 err1: 534 518 omap_dss_stop_device(dssdev); 535 519 err0:
+22 -20
drivers/video/omap2/omapfb/omapfb-ioctl.c
··· 111 111 set_fb_fix(fbi); 112 112 } 113 113 114 - if (pi->enabled) { 115 - struct omap_overlay_info info; 114 + if (!pi->enabled) { 115 + r = ovl->disable(ovl); 116 + if (r) 117 + goto undo; 118 + } 116 119 120 + if (pi->enabled) { 117 121 r = omapfb_setup_overlay(fbi, ovl, pi->pos_x, pi->pos_y, 118 122 pi->out_width, pi->out_height); 119 123 if (r) 120 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 125 } else { 131 126 struct omap_overlay_info info; 132 127 133 128 ovl->get_overlay_info(ovl, &info); 134 129 135 - info.enabled = pi->enabled; 136 130 info.pos_x = pi->pos_x; 137 131 info.pos_y = pi->pos_y; 138 132 info.out_width = pi->out_width; ··· 139 145 140 146 if (ovl->manager) 141 147 ovl->manager->apply(ovl->manager); 148 + 149 + if (pi->enabled) { 150 + r = ovl->enable(ovl); 151 + if (r) 152 + goto undo; 153 + } 142 154 143 155 /* Release the locks in a specific order to keep lockdep happy */ 144 156 if (old_rg->id > new_rg->id) { ··· 189 189 memset(pi, 0, sizeof(*pi)); 190 190 } else { 191 191 struct omap_overlay *ovl; 192 - struct omap_overlay_info *ovli; 192 + struct omap_overlay_info ovli; 193 193 194 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; 198 - pi->pos_y = ovli->pos_y; 199 - pi->enabled = ovli->enabled; 197 + pi->pos_x = ovli.pos_x; 198 + pi->pos_y = ovli.pos_y; 199 + pi->enabled = ovl->is_enabled(ovl); 200 200 pi->channel_out = 0; /* xxx */ 201 201 pi->mirror = 0; 202 202 pi->mem_idx = get_mem_idx(ofbi); 203 - pi->out_width = ovli->out_width; 204 - pi->out_height = ovli->out_height; 203 + pi->out_width = ovli.out_width; 204 + pi->out_height = ovli.out_height; 205 205 } 206 206 207 207 return 0; ··· 238 238 continue; 239 239 240 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 244 r = -EBUSY; 243 245 goto out; 244 246 }
+10 -4
drivers/video/omap2/omapfb/omapfb-main.c
··· 970 970 outh = var->yres; 971 971 } 972 972 } else { 973 - outw = ovl->info.out_width; 974 - outh = ovl->info.out_height; 973 + struct omap_overlay_info info; 974 + ovl->get_overlay_info(ovl, &info); 975 + outw = info.out_width; 976 + outh = info.out_height; 975 977 } 976 978 977 979 if (init) { 978 980 posx = 0; 979 981 posy = 0; 980 982 } else { 981 - posx = ovl->info.pos_x; 982 - posy = ovl->info.pos_y; 983 + struct omap_overlay_info info; 984 + ovl->get_overlay_info(ovl, &info); 985 + posx = info.pos_x; 986 + posy = info.pos_y; 983 987 } 984 988 985 989 r = omapfb_setup_overlay(fbi, ovl, posx, posy, outw, outh); ··· 2070 2066 2071 2067 if (ofbi->num_overlays > 0) { 2072 2068 struct omap_overlay *ovl = ofbi->overlays[0]; 2069 + 2070 + ovl->manager->apply(ovl->manager); 2073 2071 2074 2072 r = omapfb_overlay_enable(ovl, 1); 2075 2073
+3 -1
drivers/video/omap2/omapfb/omapfb-sysfs.c
··· 473 473 continue; 474 474 475 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 479 r = -EBUSY; 478 480 goto out; 479 481 }
+4 -7
drivers/video/omap2/omapfb/omapfb.h
··· 181 181 static inline int omapfb_overlay_enable(struct omap_overlay *ovl, 182 182 int enable) 183 183 { 184 - struct omap_overlay_info info; 185 - 186 - ovl->get_overlay_info(ovl, &info); 187 - if (info.enabled == enable) 188 - return 0; 189 - info.enabled = enable; 190 - return ovl->set_overlay_info(ovl, &info); 184 + if (enable) 185 + return ovl->enable(ovl); 186 + else 187 + return ovl->disable(ovl); 191 188 } 192 189 193 190 static inline struct omapfb2_mem_region *
+1 -12
drivers/video/pnx4008/pnxrgbfb.c
··· 193 193 .remove = rgbfb_remove, 194 194 }; 195 195 196 - static int __init rgbfb_init(void) 197 - { 198 - return platform_driver_register(&rgbfb_driver); 199 - } 200 - 201 - static void __exit rgbfb_exit(void) 202 - { 203 - platform_driver_unregister(&rgbfb_driver); 204 - } 205 - 206 - module_init(rgbfb_init); 207 - module_exit(rgbfb_exit); 196 + module_platform_driver(rgbfb_driver); 208 197 209 198 MODULE_LICENSE("GPL");
+1 -12
drivers/video/pnx4008/sdum.c
··· 856 856 .resume = sdum_resume, 857 857 }; 858 858 859 - int __init sdum_init(void) 860 - { 861 - return platform_driver_register(&sdum_driver); 862 - } 863 - 864 - static void __exit sdum_exit(void) 865 - { 866 - platform_driver_unregister(&sdum_driver); 867 - }; 868 - 869 - module_init(sdum_init); 870 - module_exit(sdum_exit); 859 + module_platform_driver(sdum_driver); 871 860 872 861 MODULE_LICENSE("GPL");
+1 -11
drivers/video/pxa168fb.c
··· 832 832 .remove = __devexit_p(pxa168fb_remove), 833 833 }; 834 834 835 - static int __init pxa168fb_init(void) 836 - { 837 - return platform_driver_register(&pxa168fb_driver); 838 - } 839 - module_init(pxa168fb_init); 840 - 841 - static void __exit pxa168fb_exit(void) 842 - { 843 - platform_driver_unregister(&pxa168fb_driver); 844 - } 845 - module_exit(pxa168fb_exit); 835 + module_platform_driver(pxa168fb_driver); 846 836 847 837 MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com> " 848 838 "Green Wan <gwan@marvell.com>");
+1 -14
drivers/video/pxa3xx-gcu.c
··· 747 747 }, 748 748 }; 749 749 750 - static int __init 751 - pxa3xx_gcu_init(void) 752 - { 753 - return platform_driver_register(&pxa3xx_gcu_driver); 754 - } 755 - 756 - static void __exit 757 - pxa3xx_gcu_exit(void) 758 - { 759 - platform_driver_unregister(&pxa3xx_gcu_driver); 760 - } 761 - 762 - module_init(pxa3xx_gcu_init); 763 - module_exit(pxa3xx_gcu_exit); 750 + module_platform_driver(pxa3xx_gcu_driver); 764 751 765 752 MODULE_DESCRIPTION("PXA3xx graphics controller unit driver"); 766 753 MODULE_LICENSE("GPL");
+90 -112
drivers/video/s3c-fb.c
··· 192 192 * @regs: The mapped hardware registers. 193 193 * @variant: Variant information for this hardware. 194 194 * @enabled: A bitmask of enabled hardware windows. 195 + * @output_on: Flag if the physical output is enabled. 195 196 * @pdata: The platform configuration data passed with the device. 196 197 * @windows: The hardware windows that have been claimed. 197 198 * @irq_no: IRQ line number ··· 209 208 struct s3c_fb_variant variant; 210 209 211 210 unsigned char enabled; 211 + bool output_on; 212 212 213 213 struct s3c_fb_platdata *pdata; 214 214 struct s3c_fb_win *windows[S3C_FB_MAX_WIN]; ··· 443 441 } 444 442 445 443 /** 444 + * s3c_fb_enable() - Set the state of the main LCD output 445 + * @sfb: The main framebuffer state. 446 + * @enable: The state to set. 447 + */ 448 + static void s3c_fb_enable(struct s3c_fb *sfb, int enable) 449 + { 450 + u32 vidcon0 = readl(sfb->regs + VIDCON0); 451 + 452 + if (enable && !sfb->output_on) 453 + pm_runtime_get_sync(sfb->dev); 454 + 455 + if (enable) { 456 + vidcon0 |= VIDCON0_ENVID | VIDCON0_ENVID_F; 457 + } else { 458 + /* see the note in the framebuffer datasheet about 459 + * why you cannot take both of these bits down at the 460 + * same time. */ 461 + 462 + if (vidcon0 & VIDCON0_ENVID) { 463 + vidcon0 |= VIDCON0_ENVID; 464 + vidcon0 &= ~VIDCON0_ENVID_F; 465 + } 466 + } 467 + 468 + writel(vidcon0, sfb->regs + VIDCON0); 469 + 470 + if (!enable && sfb->output_on) 471 + pm_runtime_put_sync(sfb->dev); 472 + 473 + sfb->output_on = enable; 474 + } 475 + 476 + /** 446 477 * s3c_fb_set_par() - framebuffer request to set new framebuffer state. 447 478 * @info: The framebuffer to change. 448 479 * ··· 495 460 int clkdiv; 496 461 497 462 dev_dbg(sfb->dev, "setting framebuffer parameters\n"); 463 + 464 + pm_runtime_get_sync(sfb->dev); 498 465 499 466 shadow_protect_win(win, 1); 500 467 ··· 547 510 if (sfb->variant.is_2443) 548 511 data |= (1 << 5); 549 512 550 - data |= VIDCON0_ENVID | VIDCON0_ENVID_F; 551 513 writel(data, regs + VIDCON0); 514 + 515 + s3c_fb_enable(sfb, 1); 552 516 553 517 data = VIDTCON0_VBPD(var->upper_margin - 1) | 554 518 VIDTCON0_VFPD(var->lower_margin - 1) | ··· 612 574 } 613 575 614 576 data = WINCONx_ENWIN; 577 + sfb->enabled |= (1 << win->index); 615 578 616 579 /* note, since we have to round up the bits-per-pixel, we end up 617 580 * relying on the bitfield information for r/g/b/a to work out ··· 660 621 } else if (var->transp.length == 1) 661 622 data |= WINCON1_BPPMODE_25BPP_A1888 662 623 | WINCON1_BLD_PIX; 663 - else if (var->transp.length == 4) 624 + else if ((var->transp.length == 4) || 625 + (var->transp.length == 8)) 664 626 data |= WINCON1_BPPMODE_28BPP_A4888 665 627 | WINCON1_BLD_PIX | WINCON1_ALPHA_SEL; 666 628 else ··· 693 653 writel(0x0, regs + sfb->variant.winmap + (win_no * 4)); 694 654 695 655 shadow_protect_win(win, 0); 656 + 657 + pm_runtime_put_sync(sfb->dev); 696 658 697 659 return 0; 698 660 } ··· 767 725 dev_dbg(sfb->dev, "%s: win %d: %d => rgb=%d/%d/%d\n", 768 726 __func__, win->index, regno, red, green, blue); 769 727 728 + pm_runtime_get_sync(sfb->dev); 729 + 770 730 switch (info->fix.visual) { 771 731 case FB_VISUAL_TRUECOLOR: 772 732 /* true-colour, use pseudo-palette */ ··· 796 752 break; 797 753 798 754 default: 755 + pm_runtime_put_sync(sfb->dev); 799 756 return 1; /* unknown type */ 800 757 } 801 758 759 + pm_runtime_put_sync(sfb->dev); 802 760 return 0; 803 - } 804 - 805 - /** 806 - * s3c_fb_enable() - Set the state of the main LCD output 807 - * @sfb: The main framebuffer state. 808 - * @enable: The state to set. 809 - */ 810 - static void s3c_fb_enable(struct s3c_fb *sfb, int enable) 811 - { 812 - u32 vidcon0 = readl(sfb->regs + VIDCON0); 813 - 814 - if (enable) 815 - vidcon0 |= VIDCON0_ENVID | VIDCON0_ENVID_F; 816 - else { 817 - /* see the note in the framebuffer datasheet about 818 - * why you cannot take both of these bits down at the 819 - * same time. */ 820 - 821 - if (!(vidcon0 & VIDCON0_ENVID)) 822 - return; 823 - 824 - vidcon0 |= VIDCON0_ENVID; 825 - vidcon0 &= ~VIDCON0_ENVID_F; 826 - } 827 - 828 - writel(vidcon0, sfb->regs + VIDCON0); 829 761 } 830 762 831 763 /** ··· 820 800 821 801 dev_dbg(sfb->dev, "blank mode %d\n", blank_mode); 822 802 803 + pm_runtime_get_sync(sfb->dev); 804 + 823 805 wincon = readl(sfb->regs + sfb->variant.wincon + (index * 4)); 824 806 825 807 switch (blank_mode) { ··· 832 810 833 811 case FB_BLANK_NORMAL: 834 812 /* disable the DMA and display 0x0 (black) */ 813 + shadow_protect_win(win, 1); 835 814 writel(WINxMAP_MAP | WINxMAP_MAP_COLOUR(0x0), 836 815 sfb->regs + sfb->variant.winmap + (index * 4)); 816 + shadow_protect_win(win, 0); 837 817 break; 838 818 839 819 case FB_BLANK_UNBLANK: 820 + shadow_protect_win(win, 1); 840 821 writel(0x0, sfb->regs + sfb->variant.winmap + (index * 4)); 822 + shadow_protect_win(win, 0); 841 823 wincon |= WINCONx_ENWIN; 842 824 sfb->enabled |= (1 << index); 843 825 break; ··· 849 823 case FB_BLANK_VSYNC_SUSPEND: 850 824 case FB_BLANK_HSYNC_SUSPEND: 851 825 default: 826 + pm_runtime_put_sync(sfb->dev); 852 827 return 1; 853 828 } 854 829 830 + shadow_protect_win(win, 1); 855 831 writel(wincon, sfb->regs + sfb->variant.wincon + (index * 4)); 832 + shadow_protect_win(win, 0); 856 833 857 834 /* Check the enabled state to see if we need to be running the 858 835 * main LCD interface, as if there are no active windows then ··· 874 845 /* we're stuck with this until we can do something about overriding 875 846 * the power control using the blanking event for a single fb. 876 847 */ 877 - if (index == sfb->pdata->default_win) 848 + if (index == sfb->pdata->default_win) { 849 + shadow_protect_win(win, 1); 878 850 s3c_fb_enable(sfb, blank_mode != FB_BLANK_POWERDOWN ? 1 : 0); 851 + shadow_protect_win(win, 0); 852 + } 853 + 854 + pm_runtime_put_sync(sfb->dev); 879 855 880 856 return 0; 881 857 } ··· 904 870 void __iomem *buf = sfb->regs + win->index * 8; 905 871 unsigned int start_boff, end_boff; 906 872 873 + pm_runtime_get_sync(sfb->dev); 874 + 907 875 /* Offset in bytes to the start of the displayed area */ 908 876 start_boff = var->yoffset * info->fix.line_length; 909 877 /* X offset depends on the current bpp */ ··· 924 888 break; 925 889 default: 926 890 dev_err(sfb->dev, "invalid bpp\n"); 891 + pm_runtime_put_sync(sfb->dev); 927 892 return -EINVAL; 928 893 } 929 894 } ··· 940 903 941 904 shadow_protect_win(win, 0); 942 905 906 + pm_runtime_put_sync(sfb->dev); 943 907 return 0; 944 908 } 945 909 ··· 1030 992 if (crtc != 0) 1031 993 return -ENODEV; 1032 994 995 + pm_runtime_get_sync(sfb->dev); 996 + 1033 997 count = sfb->vsync_info.count; 1034 998 s3c_fb_enable_irq(sfb); 1035 999 ret = wait_event_interruptible_timeout(sfb->vsync_info.wait, 1036 1000 count != sfb->vsync_info.count, 1037 1001 msecs_to_jiffies(VSYNC_TIMEOUT_MSEC)); 1002 + 1003 + pm_runtime_put_sync(sfb->dev); 1004 + 1038 1005 if (ret == 0) 1039 1006 return -ETIMEDOUT; 1040 1007 ··· 1070 1027 return ret; 1071 1028 } 1072 1029 1073 - static int s3c_fb_open(struct fb_info *info, int user) 1074 - { 1075 - struct s3c_fb_win *win = info->par; 1076 - struct s3c_fb *sfb = win->parent; 1077 - 1078 - pm_runtime_get_sync(sfb->dev); 1079 - 1080 - return 0; 1081 - } 1082 - 1083 - static int s3c_fb_release(struct fb_info *info, int user) 1084 - { 1085 - struct s3c_fb_win *win = info->par; 1086 - struct s3c_fb *sfb = win->parent; 1087 - 1088 - pm_runtime_put_sync(sfb->dev); 1089 - 1090 - return 0; 1091 - } 1092 - 1093 1030 static struct fb_ops s3c_fb_ops = { 1094 1031 .owner = THIS_MODULE, 1095 - .fb_open = s3c_fb_open, 1096 - .fb_release = s3c_fb_release, 1097 1032 .fb_check_var = s3c_fb_check_var, 1098 1033 .fb_set_par = s3c_fb_set_par, 1099 1034 .fb_blank = s3c_fb_blank, ··· 1473 1452 dev_err(dev, "failed to create window %d\n", win); 1474 1453 for (; win >= 0; win--) 1475 1454 s3c_fb_release_win(sfb, sfb->windows[win]); 1476 - goto err_irq; 1455 + goto err_pm_runtime; 1477 1456 } 1478 1457 } 1479 1458 ··· 1482 1461 1483 1462 return 0; 1484 1463 1485 - err_irq: 1464 + err_pm_runtime: 1465 + pm_runtime_put_sync(sfb->dev); 1486 1466 free_irq(sfb->irq_no, sfb); 1487 1467 1488 1468 err_ioremap: ··· 1493 1471 release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res)); 1494 1472 1495 1473 err_lcd_clk: 1474 + pm_runtime_disable(sfb->dev); 1475 + 1496 1476 if (!sfb->variant.has_clksel) { 1497 1477 clk_disable(sfb->lcd_clk); 1498 1478 clk_put(sfb->lcd_clk); ··· 1548 1524 return 0; 1549 1525 } 1550 1526 1551 - #ifdef CONFIG_PM 1527 + #ifdef CONFIG_PM_SLEEP 1552 1528 static int s3c_fb_suspend(struct device *dev) 1553 1529 { 1554 1530 struct platform_device *pdev = to_platform_device(dev); ··· 1595 1571 1596 1572 for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) { 1597 1573 void __iomem *regs = sfb->regs + sfb->variant.keycon; 1574 + win = sfb->windows[win_no]; 1575 + if (!win) 1576 + continue; 1598 1577 1578 + shadow_protect_win(win, 1); 1599 1579 regs += (win_no * 8); 1600 1580 writel(0xffffff, regs + WKEYCON0); 1601 1581 writel(0xffffff, regs + WKEYCON1); 1582 + shadow_protect_win(win, 0); 1602 1583 } 1603 1584 1604 1585 /* restore framebuffers */ ··· 1618 1589 1619 1590 return 0; 1620 1591 } 1592 + #endif 1621 1593 1594 + #ifdef CONFIG_PM_RUNTIME 1622 1595 static int s3c_fb_runtime_suspend(struct device *dev) 1623 1596 { 1624 1597 struct platform_device *pdev = to_platform_device(dev); 1625 1598 struct s3c_fb *sfb = platform_get_drvdata(pdev); 1626 - struct s3c_fb_win *win; 1627 - int win_no; 1628 - 1629 - for (win_no = S3C_FB_MAX_WIN - 1; win_no >= 0; win_no--) { 1630 - win = sfb->windows[win_no]; 1631 - if (!win) 1632 - continue; 1633 - 1634 - /* use the blank function to push into power-down */ 1635 - s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo); 1636 - } 1637 1599 1638 1600 if (!sfb->variant.has_clksel) 1639 1601 clk_disable(sfb->lcd_clk); 1640 1602 1641 1603 clk_disable(sfb->bus_clk); 1604 + 1642 1605 return 0; 1643 1606 } 1644 1607 ··· 1639 1618 struct platform_device *pdev = to_platform_device(dev); 1640 1619 struct s3c_fb *sfb = platform_get_drvdata(pdev); 1641 1620 struct s3c_fb_platdata *pd = sfb->pdata; 1642 - struct s3c_fb_win *win; 1643 - int win_no; 1644 1621 1645 1622 clk_enable(sfb->bus_clk); 1646 1623 ··· 1649 1630 pd->setup_gpio(); 1650 1631 writel(pd->vidcon1, sfb->regs + VIDCON1); 1651 1632 1652 - /* zero all windows before we do anything */ 1653 - for (win_no = 0; win_no < sfb->variant.nr_windows; win_no++) 1654 - s3c_fb_clear_win(sfb, win_no); 1655 - 1656 - for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) { 1657 - void __iomem *regs = sfb->regs + sfb->variant.keycon; 1658 - 1659 - regs += (win_no * 8); 1660 - writel(0xffffff, regs + WKEYCON0); 1661 - writel(0xffffff, regs + WKEYCON1); 1662 - } 1663 - 1664 - /* restore framebuffers */ 1665 - for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) { 1666 - win = sfb->windows[win_no]; 1667 - if (!win) 1668 - continue; 1669 - 1670 - dev_dbg(&pdev->dev, "resuming window %d\n", win_no); 1671 - s3c_fb_set_par(win->fbinfo); 1672 - } 1673 - 1674 1633 return 0; 1675 1634 } 1676 - 1677 - #else 1678 - #define s3c_fb_suspend NULL 1679 - #define s3c_fb_resume NULL 1680 - #define s3c_fb_runtime_suspend NULL 1681 - #define s3c_fb_runtime_resume NULL 1682 1635 #endif 1683 - 1684 1636 1685 1637 #define VALID_BPP124 (VALID_BPP(1) | VALID_BPP(2) | VALID_BPP(4)) 1686 1638 #define VALID_BPP1248 (VALID_BPP124 | VALID_BPP(8)) ··· 1975 1985 MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids); 1976 1986 1977 1987 static const struct dev_pm_ops s3cfb_pm_ops = { 1978 - .suspend = s3c_fb_suspend, 1979 - .resume = s3c_fb_resume, 1980 - .runtime_suspend = s3c_fb_runtime_suspend, 1981 - .runtime_resume = s3c_fb_runtime_resume, 1988 + SET_SYSTEM_SLEEP_PM_OPS(s3c_fb_suspend, s3c_fb_resume) 1989 + SET_RUNTIME_PM_OPS(s3c_fb_runtime_suspend, s3c_fb_runtime_resume, 1990 + NULL) 1982 1991 }; 1983 1992 1984 1993 static struct platform_driver s3c_fb_driver = { ··· 1991 2002 }, 1992 2003 }; 1993 2004 1994 - static int __init s3c_fb_init(void) 1995 - { 1996 - return platform_driver_register(&s3c_fb_driver); 1997 - } 1998 - 1999 - static void __exit s3c_fb_cleanup(void) 2000 - { 2001 - platform_driver_unregister(&s3c_fb_driver); 2002 - } 2003 - 2004 - module_init(s3c_fb_init); 2005 - module_exit(s3c_fb_cleanup); 2005 + module_platform_driver(s3c_fb_driver); 2006 2006 2007 2007 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); 2008 2008 MODULE_DESCRIPTION("Samsung S3C SoC Framebuffer driver");
+15 -14
drivers/video/s3c2410fb.c
··· 26 26 #include <linux/platform_device.h> 27 27 #include <linux/clk.h> 28 28 #include <linux/cpufreq.h> 29 + #include <linux/io.h> 29 30 30 - #include <asm/io.h> 31 31 #include <asm/div64.h> 32 32 33 33 #include <asm/mach/map.h> ··· 45 45 #ifdef CONFIG_FB_S3C2410_DEBUG 46 46 static int debug = 1; 47 47 #else 48 - static int debug = 0; 48 + static int debug; 49 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 53 /* useful functions */ 54 54 ··· 567 567 568 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 571 s3c2410fb_lcd_enable(fbi, 0); 572 - } else { 572 + else 573 573 s3c2410fb_lcd_enable(fbi, 1); 574 - } 575 574 576 575 if (blank_mode == FB_BLANK_UNBLANK) 577 576 writel(0x0, tpal_reg); ··· 811 812 #endif 812 813 813 814 814 - static char driver_name[] = "s3c2410fb"; 815 + static const char driver_name[] = "s3c2410fb"; 815 816 816 817 static int __devinit s3c24xxfb_probe(struct platform_device *pdev, 817 818 enum s3c_drv_type drv_type) ··· 880 881 goto release_mem; 881 882 } 882 883 883 - info->irq_base = info->io + ((drv_type == DRV_S3C2412) ? S3C2412_LCDINTBASE : S3C2410_LCDINTBASE); 884 + if (drv_type == DRV_S3C2412) 885 + info->irq_base = info->io + S3C2412_LCDINTBASE; 886 + else 887 + info->irq_base = info->io + S3C2410_LCDINTBASE; 884 888 885 889 dprintk("devinit\n"); 886 890 ··· 929 927 clk_enable(info->clk); 930 928 dprintk("got and enabled clock\n"); 931 929 932 - msleep(1); 930 + usleep_range(1000, 1000); 933 931 934 932 info->clk_rate = clk_get_rate(info->clk); 935 933 ··· 977 975 978 976 /* create device files */ 979 977 ret = device_create_file(&pdev->dev, &dev_attr_debug); 980 - if (ret) { 978 + if (ret) 981 979 printk(KERN_ERR "failed to add debug attribute\n"); 982 - } 983 980 984 981 printk(KERN_INFO "fb%d: %s frame buffer device\n", 985 982 fbinfo->node, fbinfo->fix.id); ··· 1028 1027 s3c2410fb_cpufreq_deregister(info); 1029 1028 1030 1029 s3c2410fb_lcd_enable(info, 0); 1031 - msleep(1); 1030 + usleep_range(1000, 1000); 1032 1031 1033 1032 s3c2410fb_unmap_video_memory(fbinfo); 1034 1033 ··· 1065 1064 * the LCD DMA engine is not going to get back on the bus 1066 1065 * before the clock goes off again (bjd) */ 1067 1066 1068 - msleep(1); 1067 + usleep_range(1000, 1000); 1069 1068 clk_disable(info->clk); 1070 1069 1071 1070 return 0; ··· 1077 1076 struct s3c2410fb_info *info = fbinfo->par; 1078 1077 1079 1078 clk_enable(info->clk); 1080 - msleep(1); 1079 + usleep_range(1000, 1000); 1081 1080 1082 1081 s3c2410fb_init_registers(fbinfo); 1083 1082
+28 -2
drivers/video/s3fb.c
··· 727 727 if (par->chip == CHIP_988_VIRGE_VX) { 728 728 vga_wcrt(par->state.vgabase, 0x50, 0x00); 729 729 vga_wcrt(par->state.vgabase, 0x67, 0x50); 730 - 730 + msleep(10); /* screen remains blank sometimes without this */ 731 731 vga_wcrt(par->state.vgabase, 0x63, (mode <= 2) ? 0x90 : 0x09); 732 732 vga_wcrt(par->state.vgabase, 0x66, 0x90); 733 733 } ··· 901 901 902 902 /* Set Data Transfer Position */ 903 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 906 svga_wcrt_multi(par->state.vgabase, s3_dtpc_regs, value); 906 907 907 908 memset_io(info->screen_base, 0x00, screen_size); ··· 1215 1214 break; 1216 1215 case 3: /* 2MB */ 1217 1216 info->screen_size = 2 << 20; 1217 + break; 1218 + } 1219 + } else if (par->chip == CHIP_988_VIRGE_VX) { 1220 + switch ((regval & 0x60) >> 5) { 1221 + case 0: /* 2MB */ 1222 + info->screen_size = 2 << 20; 1223 + break; 1224 + case 1: /* 4MB */ 1225 + info->screen_size = 4 << 20; 1226 + break; 1227 + case 2: /* 6MB */ 1228 + info->screen_size = 6 << 20; 1229 + break; 1230 + case 3: /* 8MB */ 1231 + info->screen_size = 8 << 20; 1232 + break; 1233 + } 1234 + /* off-screen memory */ 1235 + regval = vga_rcrt(par->state.vgabase, 0x37); 1236 + switch ((regval & 0x60) >> 5) { 1237 + case 1: /* 4MB */ 1238 + info->screen_size -= 4 << 20; 1239 + break; 1240 + case 2: /* 2MB */ 1241 + info->screen_size -= 2 << 20; 1218 1242 break; 1219 1243 } 1220 1244 } else
+1 -1
drivers/video/sbuslib.c
··· 76 76 map_offset = (physbase + map[i].poff) & POFF_MASK; 77 77 break; 78 78 } 79 - if (!map_size){ 79 + if (!map_size) { 80 80 page += PAGE_SIZE; 81 81 continue; 82 82 }
+1 -12
drivers/video/sh7760fb.c
··· 585 585 .remove = __devexit_p(sh7760fb_remove), 586 586 }; 587 587 588 - static int __init sh7760fb_init(void) 589 - { 590 - return platform_driver_register(&sh7760_lcdc_driver); 591 - } 592 - 593 - static void __exit sh7760fb_exit(void) 594 - { 595 - platform_driver_unregister(&sh7760_lcdc_driver); 596 - } 597 - 598 - module_init(sh7760fb_init); 599 - module_exit(sh7760fb_exit); 588 + module_platform_driver(sh7760_lcdc_driver); 600 589 601 590 MODULE_AUTHOR("Nobuhiro Iwamatsu, Manuel Lauss"); 602 591 MODULE_DESCRIPTION("FBdev for SH7760/63 integrated LCD Controller");
+131 -87
drivers/video/sh_mipi_dsi.c
··· 8 8 * published by the Free Software Foundation. 9 9 */ 10 10 11 + #include <linux/bitmap.h> 11 12 #include <linux/clk.h> 12 13 #include <linux/delay.h> 13 14 #include <linux/init.h> ··· 42 41 #define VMCTR1 0x0020 43 42 #define VMCTR2 0x0024 44 43 #define VMLEN1 0x0028 44 + #define VMLEN2 0x002c 45 45 #define CMTSRTREQ 0x0070 46 46 #define CMTSRTCTR 0x00d0 47 47 ··· 53 51 void __iomem *base; 54 52 void __iomem *linkbase; 55 53 struct clk *dsit_clk; 56 - struct clk *dsip_clk; 57 - struct device *dev; 54 + struct platform_device *pdev; 58 55 59 56 void *next_board_data; 60 57 void (*next_display_on)(void *board_data, struct fb_info *info); ··· 125 124 sh_mipi_dsi_enable(mipi, false); 126 125 } 127 126 128 - static void mipi_display_on(void *arg, struct fb_info *info) 129 - { 130 - struct sh_mipi *mipi = arg; 131 - 132 - pm_runtime_get_sync(mipi->dev); 133 - sh_mipi_dsi_enable(mipi, true); 134 - 135 - if (mipi->next_display_on) 136 - mipi->next_display_on(mipi->next_board_data, info); 137 - } 138 - 139 - static void mipi_display_off(void *arg) 140 - { 141 - struct sh_mipi *mipi = arg; 142 - 143 - if (mipi->next_display_off) 144 - mipi->next_display_off(mipi->next_board_data); 145 - 146 - sh_mipi_dsi_enable(mipi, false); 147 - pm_runtime_put(mipi->dev); 148 - } 149 - 150 127 static int __init sh_mipi_setup(struct sh_mipi *mipi, 151 128 struct sh_mipi_dsi_info *pdata) 152 129 { 153 130 void __iomem *base = mipi->base; 154 131 struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan; 155 - u32 pctype, datatype, pixfmt, linelength, vmctr2 = 0x00e00000; 132 + u32 pctype, datatype, pixfmt, linelength, vmctr2; 133 + u32 tmp, top, bottom, delay, div; 156 134 bool yuv; 135 + int bpp; 157 136 158 137 /* 159 138 * Select data format. MIPI DSI is not hot-pluggable, so, we just use ··· 234 253 (!yuv && ch->interface_type != RGB24)) 235 254 return -EINVAL; 236 255 256 + if (!pdata->lane) 257 + return -EINVAL; 258 + 237 259 /* reset DSI link */ 238 260 iowrite32(0x00000001, base + SYSCTRL); 239 261 /* Hold reset for 100 cycles of the slowest of bus, HS byte and LP clock */ ··· 245 261 246 262 /* setup DSI link */ 247 263 248 - /* 249 - * Default = ULPS enable | 250 - * Contention detection enabled | 251 - * EoT packet transmission enable | 252 - * CRC check enable | 253 - * ECC check enable 254 - * additionally enable first two lanes 255 - */ 256 - iowrite32(0x00003703, base + SYSCONF); 257 264 /* 258 265 * T_wakeup = 0x7000 259 266 * T_hs-trail = 3 ··· 265 290 iowrite32(0x0fffffff, base + TATOVSET); 266 291 /* Peripheral reset timeout, default 0xffffffff */ 267 292 iowrite32(0x0fffffff, base + PRTOVSET); 268 - /* Enable timeout counters */ 269 - iowrite32(0x00000f00, base + DSICTRL); 270 293 /* Interrupts not used, disable all */ 271 294 iowrite32(0, base + DSIINTE); 272 295 /* DSI-Tx bias on */ 273 296 iowrite32(0x00000001, base + PHYCTRL); 274 297 udelay(200); 275 - /* Deassert resets, power on, set multiplier */ 276 - iowrite32(0x03070b01, base + PHYCTRL); 298 + /* Deassert resets, power on */ 299 + iowrite32(0x03070001, base + PHYCTRL); 300 + 301 + /* 302 + * Default = ULPS enable | 303 + * Contention detection enabled | 304 + * EoT packet transmission enable | 305 + * CRC check enable | 306 + * ECC check enable 307 + */ 308 + bitmap_fill((unsigned long *)&tmp, pdata->lane); 309 + tmp |= 0x00003700; 310 + iowrite32(tmp, base + SYSCONF); 277 311 278 312 /* setup l-bridge */ 279 313 ··· 300 316 * Non-burst mode with sync pulses: VSE and HSE are output, 301 317 * HSA period allowed, no commands in LP 302 318 */ 319 + vmctr2 = 0; 320 + if (pdata->flags & SH_MIPI_DSI_VSEE) 321 + vmctr2 |= 1 << 23; 322 + if (pdata->flags & SH_MIPI_DSI_HSEE) 323 + vmctr2 |= 1 << 22; 324 + if (pdata->flags & SH_MIPI_DSI_HSAE) 325 + vmctr2 |= 1 << 21; 326 + if (pdata->flags & SH_MIPI_DSI_BL2E) 327 + vmctr2 |= 1 << 17; 303 328 if (pdata->flags & SH_MIPI_DSI_HSABM) 304 - vmctr2 |= 0x20; 305 - if (pdata->flags & SH_MIPI_DSI_HSPBM) 306 - vmctr2 |= 0x10; 329 + vmctr2 |= 1 << 5; 330 + if (pdata->flags & SH_MIPI_DSI_HBPBM) 331 + vmctr2 |= 1 << 4; 332 + if (pdata->flags & SH_MIPI_DSI_HFPBM) 333 + vmctr2 |= 1 << 3; 307 334 iowrite32(vmctr2, mipi->linkbase + VMCTR2); 308 335 309 336 /* 310 - * 0x660 = 1632 bytes per line (RGB24, 544 pixels: see 311 - * sh_mobile_lcdc_info.ch[0].lcd_cfg[0].xres), HSALEN = 1 - default 312 - * (unused if VMCTR2[HSABM] = 0) 337 + * VMLEN1 = RGBLEN | HSALEN 338 + * 339 + * see 340 + * Video mode - Blanking Packet setting 313 341 */ 314 - iowrite32(1 | (linelength << 16), mipi->linkbase + VMLEN1); 342 + top = linelength << 16; /* RGBLEN */ 343 + bottom = 0x00000001; 344 + if (pdata->flags & SH_MIPI_DSI_HSABM) /* HSALEN */ 345 + bottom = (pdata->lane * ch->lcd_cfg[0].hsync_len) - 10; 346 + iowrite32(top | bottom , mipi->linkbase + VMLEN1); 347 + 348 + /* 349 + * VMLEN2 = HBPLEN | HFPLEN 350 + * 351 + * see 352 + * Video mode - Blanking Packet setting 353 + */ 354 + top = 0x00010000; 355 + bottom = 0x00000001; 356 + delay = 0; 357 + 358 + div = 1; /* HSbyteCLK is calculation base 359 + * HS4divCLK = HSbyteCLK/2 360 + * HS6divCLK is not supported for now */ 361 + if (pdata->flags & SH_MIPI_DSI_HS4divCLK) 362 + div = 2; 363 + 364 + if (pdata->flags & SH_MIPI_DSI_HFPBM) { /* HBPLEN */ 365 + top = ch->lcd_cfg[0].hsync_len + ch->lcd_cfg[0].left_margin; 366 + top = ((pdata->lane * top / div) - 10) << 16; 367 + } 368 + if (pdata->flags & SH_MIPI_DSI_HBPBM) { /* HFPLEN */ 369 + bottom = ch->lcd_cfg[0].right_margin; 370 + bottom = (pdata->lane * bottom / div) - 12; 371 + } 372 + 373 + bpp = linelength / ch->lcd_cfg[0].xres; /* byte / pixel */ 374 + if ((pdata->lane / div) > bpp) { 375 + tmp = ch->lcd_cfg[0].xres / bpp; /* output cycle */ 376 + tmp = ch->lcd_cfg[0].xres - tmp; /* (input - output) cycle */ 377 + delay = (pdata->lane * tmp); 378 + } 379 + 380 + iowrite32(top | (bottom + delay) , mipi->linkbase + VMLEN2); 315 381 316 382 msleep(5); 317 383 ··· 386 352 pixfmt << 4); 387 353 sh_mipi_dcs(ch->chan, MIPI_DCS_SET_DISPLAY_ON); 388 354 355 + /* Enable timeout counters */ 356 + iowrite32(0x00000f00, base + DSICTRL); 357 + 389 358 return 0; 359 + } 360 + 361 + static void mipi_display_on(void *arg, struct fb_info *info) 362 + { 363 + struct sh_mipi *mipi = arg; 364 + struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data; 365 + int ret; 366 + 367 + pm_runtime_get_sync(&mipi->pdev->dev); 368 + 369 + ret = pdata->set_dot_clock(mipi->pdev, mipi->base, 1); 370 + if (ret < 0) 371 + goto mipi_display_on_fail1; 372 + 373 + ret = sh_mipi_setup(mipi, pdata); 374 + if (ret < 0) 375 + goto mipi_display_on_fail2; 376 + 377 + sh_mipi_dsi_enable(mipi, true); 378 + 379 + if (mipi->next_display_on) 380 + mipi->next_display_on(mipi->next_board_data, info); 381 + 382 + return; 383 + 384 + mipi_display_on_fail1: 385 + pm_runtime_put_sync(&mipi->pdev->dev); 386 + mipi_display_on_fail2: 387 + pdata->set_dot_clock(mipi->pdev, mipi->base, 0); 388 + } 389 + 390 + static void mipi_display_off(void *arg) 391 + { 392 + struct sh_mipi *mipi = arg; 393 + struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data; 394 + 395 + if (mipi->next_display_off) 396 + mipi->next_display_off(mipi->next_board_data); 397 + 398 + sh_mipi_dsi_enable(mipi, false); 399 + 400 + pdata->set_dot_clock(mipi->pdev, mipi->base, 0); 401 + 402 + pm_runtime_put_sync(&mipi->pdev->dev); 390 403 } 391 404 392 405 static int __init sh_mipi_probe(struct platform_device *pdev) ··· 444 363 struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); 445 364 unsigned long rate, f_current; 446 365 int idx = pdev->id, ret; 447 - char dsip_clk[] = "dsi.p_clk"; 448 366 449 367 if (!res || !res2 || idx >= ARRAY_SIZE(mipi_dsi) || !pdata) 450 368 return -ENODEV; 369 + 370 + if (!pdata->set_dot_clock) 371 + return -EINVAL; 451 372 452 373 mutex_lock(&array_lock); 453 374 if (idx < 0) ··· 491 408 goto emap2; 492 409 } 493 410 494 - mipi->dev = &pdev->dev; 411 + mipi->pdev = pdev; 495 412 496 413 mipi->dsit_clk = clk_get(&pdev->dev, "dsit_clk"); 497 414 if (IS_ERR(mipi->dsit_clk)) { ··· 511 428 512 429 dev_dbg(&pdev->dev, "DSI-T clk %lu -> %lu\n", f_current, rate); 513 430 514 - sprintf(dsip_clk, "dsi%1.1dp_clk", idx); 515 - mipi->dsip_clk = clk_get(&pdev->dev, dsip_clk); 516 - if (IS_ERR(mipi->dsip_clk)) { 517 - ret = PTR_ERR(mipi->dsip_clk); 518 - goto eclkpget; 519 - } 520 - 521 - f_current = clk_get_rate(mipi->dsip_clk); 522 - /* Between 10 and 50MHz */ 523 - rate = clk_round_rate(mipi->dsip_clk, 24000000); 524 - if (rate > 0 && rate != f_current) 525 - ret = clk_set_rate(mipi->dsip_clk, rate); 526 - else 527 - ret = rate; 528 - if (ret < 0) 529 - goto esetprate; 530 - 531 - dev_dbg(&pdev->dev, "DSI-P clk %lu -> %lu\n", f_current, rate); 532 - 533 - msleep(10); 534 - 535 431 ret = clk_enable(mipi->dsit_clk); 536 432 if (ret < 0) 537 433 goto eclkton; 538 - 539 - ret = clk_enable(mipi->dsip_clk); 540 - if (ret < 0) 541 - goto eclkpon; 542 434 543 435 mipi_dsi[idx] = mipi; 544 436 545 437 pm_runtime_enable(&pdev->dev); 546 438 pm_runtime_resume(&pdev->dev); 547 - 548 - ret = sh_mipi_setup(mipi, pdata); 549 - if (ret < 0) 550 - goto emipisetup; 551 439 552 440 mutex_unlock(&array_lock); 553 441 platform_set_drvdata(pdev, mipi); ··· 536 482 537 483 return 0; 538 484 539 - emipisetup: 540 - mipi_dsi[idx] = NULL; 541 - pm_runtime_disable(&pdev->dev); 542 - clk_disable(mipi->dsip_clk); 543 - eclkpon: 544 - clk_disable(mipi->dsit_clk); 545 485 eclkton: 546 - esetprate: 547 - clk_put(mipi->dsip_clk); 548 - eclkpget: 549 486 esettrate: 550 487 clk_put(mipi->dsit_clk); 551 488 eclktget: ··· 587 542 pdata->lcd_chan->board_cfg.board_data = NULL; 588 543 589 544 pm_runtime_disable(&pdev->dev); 590 - clk_disable(mipi->dsip_clk); 591 545 clk_disable(mipi->dsit_clk); 592 546 clk_put(mipi->dsit_clk); 593 - clk_put(mipi->dsip_clk); 547 + 594 548 iounmap(mipi->linkbase); 595 549 if (res2) 596 550 release_mem_region(res2->start, resource_size(res2));
+242 -133
drivers/video/sh_mobile_lcdcfb.c
··· 17 17 #include <linux/platform_device.h> 18 18 #include <linux/dma-mapping.h> 19 19 #include <linux/interrupt.h> 20 + #include <linux/videodev2.h> 20 21 #include <linux/vmalloc.h> 21 22 #include <linux/ioctl.h> 22 23 #include <linux/slab.h> ··· 103 102 struct sh_mobile_lcdc_chan ch[2]; 104 103 struct notifier_block notifier; 105 104 int started; 106 - int forced_bpp; /* 2 channel LCDC must share bpp setting */ 105 + int forced_fourcc; /* 2 channel LCDC must share fourcc setting */ 107 106 struct sh_mobile_meram_info *meram_dev; 108 107 }; 109 108 ··· 215 214 lcdc_sys_write_data, 216 215 lcdc_sys_read_data, 217 216 }; 217 + 218 + static int sh_mobile_format_fourcc(const struct fb_var_screeninfo *var) 219 + { 220 + if (var->grayscale > 1) 221 + return var->grayscale; 222 + 223 + switch (var->bits_per_pixel) { 224 + case 16: 225 + return V4L2_PIX_FMT_RGB565; 226 + case 24: 227 + return V4L2_PIX_FMT_BGR24; 228 + case 32: 229 + return V4L2_PIX_FMT_BGR32; 230 + default: 231 + return 0; 232 + } 233 + } 234 + 235 + static int sh_mobile_format_is_fourcc(const struct fb_var_screeninfo *var) 236 + { 237 + return var->grayscale > 1; 238 + } 239 + 240 + static bool sh_mobile_format_is_yuv(const struct fb_var_screeninfo *var) 241 + { 242 + if (var->grayscale <= 1) 243 + return false; 244 + 245 + switch (var->grayscale) { 246 + case V4L2_PIX_FMT_NV12: 247 + case V4L2_PIX_FMT_NV21: 248 + case V4L2_PIX_FMT_NV16: 249 + case V4L2_PIX_FMT_NV61: 250 + case V4L2_PIX_FMT_NV24: 251 + case V4L2_PIX_FMT_NV42: 252 + return true; 253 + 254 + default: 255 + return false; 256 + } 257 + } 218 258 219 259 static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv) 220 260 { ··· 462 420 tmp = ((display_var->xres & 7) << 24) | 463 421 ((display_h_total & 7) << 16) | 464 422 ((display_var->hsync_len & 7) << 8) | 465 - hsync_pos; 423 + (hsync_pos & 7); 466 424 lcdc_write_chan(ch, LDHAJR, tmp); 467 425 } 468 426 ··· 477 435 { 478 436 struct sh_mobile_lcdc_chan *ch; 479 437 unsigned long tmp; 480 - int bpp = 0; 481 438 int k, m; 482 439 483 440 /* Enable LCDC channels. Read data from external memory, avoid using the ··· 494 453 ch = &priv->ch[k]; 495 454 if (!ch->enabled) 496 455 continue; 497 - 498 - if (!bpp) 499 - bpp = ch->info->var.bits_per_pixel; 500 456 501 457 /* Power supply */ 502 458 lcdc_write_chan(ch, LDPMR, 0); ··· 525 487 526 488 sh_mobile_lcdc_geometry(ch); 527 489 528 - if (ch->info->var.nonstd) { 529 - tmp = (ch->info->var.nonstd << 16); 530 - switch (ch->info->var.bits_per_pixel) { 531 - case 12: 532 - tmp |= LDDFR_YF_420; 490 + switch (sh_mobile_format_fourcc(&ch->info->var)) { 491 + case V4L2_PIX_FMT_RGB565: 492 + tmp = LDDFR_PKF_RGB16; 493 + break; 494 + case V4L2_PIX_FMT_BGR24: 495 + tmp = LDDFR_PKF_RGB24; 496 + break; 497 + case V4L2_PIX_FMT_BGR32: 498 + tmp = LDDFR_PKF_ARGB32; 499 + break; 500 + case V4L2_PIX_FMT_NV12: 501 + case V4L2_PIX_FMT_NV21: 502 + tmp = LDDFR_CC | LDDFR_YF_420; 503 + break; 504 + case V4L2_PIX_FMT_NV16: 505 + case V4L2_PIX_FMT_NV61: 506 + tmp = LDDFR_CC | LDDFR_YF_422; 507 + break; 508 + case V4L2_PIX_FMT_NV24: 509 + case V4L2_PIX_FMT_NV42: 510 + tmp = LDDFR_CC | LDDFR_YF_444; 511 + break; 512 + } 513 + 514 + if (sh_mobile_format_is_yuv(&ch->info->var)) { 515 + switch (ch->info->var.colorspace) { 516 + case V4L2_COLORSPACE_REC709: 517 + tmp |= LDDFR_CF1; 533 518 break; 534 - case 16: 535 - tmp |= LDDFR_YF_422; 536 - break; 537 - case 24: 538 - default: 539 - tmp |= LDDFR_YF_444; 540 - break; 541 - } 542 - } else { 543 - switch (ch->info->var.bits_per_pixel) { 544 - case 16: 545 - tmp = LDDFR_PKF_RGB16; 546 - break; 547 - case 24: 548 - tmp = LDDFR_PKF_RGB24; 549 - break; 550 - case 32: 551 - default: 552 - tmp = LDDFR_PKF_ARGB32; 519 + case V4L2_COLORSPACE_JPEG: 520 + tmp |= LDDFR_CF0; 553 521 break; 554 522 } 555 523 } ··· 563 519 lcdc_write_chan(ch, LDDFR, tmp); 564 520 lcdc_write_chan(ch, LDMLSR, ch->pitch); 565 521 lcdc_write_chan(ch, LDSA1R, ch->base_addr_y); 566 - if (ch->info->var.nonstd) 522 + if (sh_mobile_format_is_yuv(&ch->info->var)) 567 523 lcdc_write_chan(ch, LDSA2R, ch->base_addr_c); 568 524 569 525 /* When using deferred I/O mode, configure the LCDC for one-shot ··· 580 536 } 581 537 582 538 /* Word and long word swap. */ 583 - if (priv->ch[0].info->var.nonstd) 539 + switch (sh_mobile_format_fourcc(&priv->ch[0].info->var)) { 540 + case V4L2_PIX_FMT_RGB565: 541 + case V4L2_PIX_FMT_NV21: 542 + case V4L2_PIX_FMT_NV61: 543 + case V4L2_PIX_FMT_NV42: 544 + tmp = LDDDSR_LS | LDDDSR_WS; 545 + break; 546 + case V4L2_PIX_FMT_BGR24: 547 + case V4L2_PIX_FMT_NV12: 548 + case V4L2_PIX_FMT_NV16: 549 + case V4L2_PIX_FMT_NV24: 584 550 tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS; 585 - else { 586 - switch (bpp) { 587 - case 16: 588 - tmp = LDDDSR_LS | LDDDSR_WS; 589 - break; 590 - case 24: 591 - tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS; 592 - break; 593 - case 32: 594 - default: 595 - tmp = LDDDSR_LS; 596 - break; 597 - } 551 + break; 552 + case V4L2_PIX_FMT_BGR32: 553 + default: 554 + tmp = LDDDSR_LS; 555 + break; 598 556 } 599 557 lcdc_write(priv, _LDDDSR, tmp); 600 558 ··· 668 622 ch->meram_enabled = 0; 669 623 } 670 624 671 - if (!ch->info->var.nonstd) 672 - pixelformat = SH_MOBILE_MERAM_PF_RGB; 673 - else if (ch->info->var.bits_per_pixel == 24) 674 - pixelformat = SH_MOBILE_MERAM_PF_NV24; 675 - else 625 + switch (sh_mobile_format_fourcc(&ch->info->var)) { 626 + case V4L2_PIX_FMT_NV12: 627 + case V4L2_PIX_FMT_NV21: 628 + case V4L2_PIX_FMT_NV16: 629 + case V4L2_PIX_FMT_NV61: 676 630 pixelformat = SH_MOBILE_MERAM_PF_NV; 631 + break; 632 + case V4L2_PIX_FMT_NV24: 633 + case V4L2_PIX_FMT_NV42: 634 + pixelformat = SH_MOBILE_MERAM_PF_NV24; 635 + break; 636 + case V4L2_PIX_FMT_RGB565: 637 + case V4L2_PIX_FMT_BGR24: 638 + case V4L2_PIX_FMT_BGR32: 639 + default: 640 + pixelformat = SH_MOBILE_MERAM_PF_RGB; 641 + break; 642 + } 677 643 678 644 ret = mdev->ops->meram_register(mdev, cfg, ch->pitch, 679 645 ch->info->var.yres, pixelformat, ··· 903 845 .xpanstep = 0, 904 846 .ypanstep = 1, 905 847 .ywrapstep = 0, 848 + .capabilities = FB_CAP_FOURCC, 906 849 }; 907 850 908 851 static void sh_mobile_lcdc_fillrect(struct fb_info *info, ··· 936 877 unsigned long new_pan_offset; 937 878 unsigned long base_addr_y, base_addr_c; 938 879 unsigned long c_offset; 880 + bool yuv = sh_mobile_format_is_yuv(&info->var); 939 881 940 - if (!info->var.nonstd) 882 + if (!yuv) 941 883 new_pan_offset = var->yoffset * info->fix.line_length 942 884 + var->xoffset * (info->var.bits_per_pixel / 8); 943 885 else ··· 952 892 953 893 /* Set the source address for the next refresh */ 954 894 base_addr_y = ch->dma_handle + new_pan_offset; 955 - if (info->var.nonstd) { 895 + if (yuv) { 956 896 /* Set y offset */ 957 897 c_offset = var->yoffset * info->fix.line_length 958 898 * (info->var.bits_per_pixel - 8) / 8; ··· 960 900 + info->var.xres * info->var.yres_virtual 961 901 + c_offset; 962 902 /* Set x offset */ 963 - if (info->var.bits_per_pixel == 24) 903 + if (sh_mobile_format_fourcc(&info->var) == V4L2_PIX_FMT_NV24) 964 904 base_addr_c += 2 * var->xoffset; 965 905 else 966 906 base_addr_c += var->xoffset; ··· 984 924 ch->base_addr_c = base_addr_c; 985 925 986 926 lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y); 987 - if (info->var.nonstd) 927 + if (yuv) 988 928 lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c); 989 929 990 930 if (lcdc_chan_is_sublcd(ch)) ··· 1160 1100 if (var->yres_virtual < var->yres) 1161 1101 var->yres_virtual = var->yres; 1162 1102 1163 - if (var->bits_per_pixel <= 16) { /* RGB 565 */ 1164 - var->bits_per_pixel = 16; 1165 - var->red.offset = 11; 1166 - var->red.length = 5; 1167 - var->green.offset = 5; 1168 - var->green.length = 6; 1169 - var->blue.offset = 0; 1170 - var->blue.length = 5; 1171 - var->transp.offset = 0; 1172 - var->transp.length = 0; 1173 - } else if (var->bits_per_pixel <= 24) { /* RGB 888 */ 1174 - var->bits_per_pixel = 24; 1175 - var->red.offset = 16; 1176 - var->red.length = 8; 1177 - var->green.offset = 8; 1178 - var->green.length = 8; 1179 - var->blue.offset = 0; 1180 - var->blue.length = 8; 1181 - var->transp.offset = 0; 1182 - var->transp.length = 0; 1183 - } else if (var->bits_per_pixel <= 32) { /* RGBA 888 */ 1184 - var->bits_per_pixel = 32; 1185 - var->red.offset = 16; 1186 - var->red.length = 8; 1187 - var->green.offset = 8; 1188 - var->green.length = 8; 1189 - var->blue.offset = 0; 1190 - var->blue.length = 8; 1191 - var->transp.offset = 24; 1192 - var->transp.length = 8; 1193 - } else 1194 - return -EINVAL; 1103 + if (sh_mobile_format_is_fourcc(var)) { 1104 + switch (var->grayscale) { 1105 + case V4L2_PIX_FMT_NV12: 1106 + case V4L2_PIX_FMT_NV21: 1107 + var->bits_per_pixel = 12; 1108 + break; 1109 + case V4L2_PIX_FMT_RGB565: 1110 + case V4L2_PIX_FMT_NV16: 1111 + case V4L2_PIX_FMT_NV61: 1112 + var->bits_per_pixel = 16; 1113 + break; 1114 + case V4L2_PIX_FMT_BGR24: 1115 + case V4L2_PIX_FMT_NV24: 1116 + case V4L2_PIX_FMT_NV42: 1117 + var->bits_per_pixel = 24; 1118 + break; 1119 + case V4L2_PIX_FMT_BGR32: 1120 + var->bits_per_pixel = 32; 1121 + break; 1122 + default: 1123 + return -EINVAL; 1124 + } 1195 1125 1196 - var->red.msb_right = 0; 1197 - var->green.msb_right = 0; 1198 - var->blue.msb_right = 0; 1199 - var->transp.msb_right = 0; 1126 + /* Default to RGB and JPEG color-spaces for RGB and YUV formats 1127 + * respectively. 1128 + */ 1129 + if (!sh_mobile_format_is_yuv(var)) 1130 + var->colorspace = V4L2_COLORSPACE_SRGB; 1131 + else if (var->colorspace != V4L2_COLORSPACE_REC709) 1132 + var->colorspace = V4L2_COLORSPACE_JPEG; 1133 + } else { 1134 + if (var->bits_per_pixel <= 16) { /* RGB 565 */ 1135 + var->bits_per_pixel = 16; 1136 + var->red.offset = 11; 1137 + var->red.length = 5; 1138 + var->green.offset = 5; 1139 + var->green.length = 6; 1140 + var->blue.offset = 0; 1141 + var->blue.length = 5; 1142 + var->transp.offset = 0; 1143 + var->transp.length = 0; 1144 + } else if (var->bits_per_pixel <= 24) { /* RGB 888 */ 1145 + var->bits_per_pixel = 24; 1146 + var->red.offset = 16; 1147 + var->red.length = 8; 1148 + var->green.offset = 8; 1149 + var->green.length = 8; 1150 + var->blue.offset = 0; 1151 + var->blue.length = 8; 1152 + var->transp.offset = 0; 1153 + var->transp.length = 0; 1154 + } else if (var->bits_per_pixel <= 32) { /* RGBA 888 */ 1155 + var->bits_per_pixel = 32; 1156 + var->red.offset = 16; 1157 + var->red.length = 8; 1158 + var->green.offset = 8; 1159 + var->green.length = 8; 1160 + var->blue.offset = 0; 1161 + var->blue.length = 8; 1162 + var->transp.offset = 24; 1163 + var->transp.length = 8; 1164 + } else 1165 + return -EINVAL; 1166 + 1167 + var->red.msb_right = 0; 1168 + var->green.msb_right = 0; 1169 + var->blue.msb_right = 0; 1170 + var->transp.msb_right = 0; 1171 + } 1200 1172 1201 1173 /* Make sure we don't exceed our allocated memory. */ 1202 1174 if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 > 1203 1175 info->fix.smem_len) 1204 1176 return -EINVAL; 1205 1177 1206 - /* only accept the forced_bpp for dual channel configurations */ 1207 - if (p->forced_bpp && p->forced_bpp != var->bits_per_pixel) 1178 + /* only accept the forced_fourcc for dual channel configurations */ 1179 + if (p->forced_fourcc && 1180 + p->forced_fourcc != sh_mobile_format_fourcc(var)) 1208 1181 return -EINVAL; 1209 1182 1210 1183 return 0; ··· 1251 1158 1252 1159 sh_mobile_lcdc_stop(ch->lcdc); 1253 1160 1254 - if (info->var.nonstd) 1161 + if (sh_mobile_format_is_yuv(&info->var)) 1255 1162 info->fix.line_length = info->var.xres; 1256 1163 else 1257 1164 info->fix.line_length = info->var.xres ··· 1261 1168 if (ret < 0) { 1262 1169 dev_err(info->dev, "%s: unable to restart LCDC\n", __func__); 1263 1170 info->fix.line_length = line_length; 1171 + } 1172 + 1173 + if (sh_mobile_format_is_fourcc(&info->var)) { 1174 + info->fix.type = FB_TYPE_FOURCC; 1175 + info->fix.visual = FB_VISUAL_FOURCC; 1176 + } else { 1177 + info->fix.type = FB_TYPE_PACKED_PIXELS; 1178 + info->fix.visual = FB_VISUAL_TRUECOLOR; 1264 1179 } 1265 1180 1266 1181 return ret; ··· 1565 1464 for (i = 0, mode = cfg->lcd_cfg; i < cfg->num_cfg; i++, mode++) { 1566 1465 unsigned int size = mode->yres * mode->xres; 1567 1466 1568 - /* NV12 buffers must have even number of lines */ 1569 - if ((cfg->nonstd) && cfg->bpp == 12 && 1570 - (mode->yres & 0x1)) { 1467 + /* NV12/NV21 buffers must have even number of lines */ 1468 + if ((cfg->fourcc == V4L2_PIX_FMT_NV12 || 1469 + cfg->fourcc == V4L2_PIX_FMT_NV21) && (mode->yres & 0x1)) { 1571 1470 dev_err(dev, "yres must be multiple of 2 for YCbCr420 " 1572 1471 "mode.\n"); 1573 1472 return -EINVAL; ··· 1584 1483 else 1585 1484 dev_dbg(dev, "Found largest videomode %ux%u\n", 1586 1485 max_mode->xres, max_mode->yres); 1587 - 1588 - /* Initialize fixed screen information. Restrict pan to 2 lines steps 1589 - * for NV12. 1590 - */ 1591 - info->fix = sh_mobile_lcdc_fix; 1592 - info->fix.smem_len = max_size * 2 * cfg->bpp / 8; 1593 - if (cfg->nonstd && cfg->bpp == 12) 1594 - info->fix.ypanstep = 2; 1595 1486 1596 1487 /* Create the mode list. */ 1597 1488 if (cfg->lcd_cfg == NULL) { ··· 1602 1509 */ 1603 1510 var = &info->var; 1604 1511 fb_videomode_to_var(var, mode); 1605 - var->bits_per_pixel = cfg->bpp; 1606 1512 var->width = cfg->lcd_size_cfg.width; 1607 1513 var->height = cfg->lcd_size_cfg.height; 1608 1514 var->yres_virtual = var->yres * 2; 1609 1515 var->activate = FB_ACTIVATE_NOW; 1610 1516 1517 + switch (cfg->fourcc) { 1518 + case V4L2_PIX_FMT_RGB565: 1519 + var->bits_per_pixel = 16; 1520 + break; 1521 + case V4L2_PIX_FMT_BGR24: 1522 + var->bits_per_pixel = 24; 1523 + break; 1524 + case V4L2_PIX_FMT_BGR32: 1525 + var->bits_per_pixel = 32; 1526 + break; 1527 + default: 1528 + var->grayscale = cfg->fourcc; 1529 + break; 1530 + } 1531 + 1532 + /* Make sure the memory size check won't fail. smem_len is initialized 1533 + * later based on var. 1534 + */ 1535 + info->fix.smem_len = UINT_MAX; 1611 1536 ret = sh_mobile_check_var(var, info); 1612 1537 if (ret) 1613 1538 return ret; 1614 1539 1540 + max_size = max_size * var->bits_per_pixel / 8 * 2; 1541 + 1615 1542 /* Allocate frame buffer memory and color map. */ 1616 - buf = dma_alloc_coherent(dev, info->fix.smem_len, &ch->dma_handle, 1617 - GFP_KERNEL); 1543 + buf = dma_alloc_coherent(dev, max_size, &ch->dma_handle, GFP_KERNEL); 1618 1544 if (!buf) { 1619 1545 dev_err(dev, "unable to allocate buffer\n"); 1620 1546 return -ENOMEM; ··· 1642 1530 ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0); 1643 1531 if (ret < 0) { 1644 1532 dev_err(dev, "unable to allocate cmap\n"); 1645 - dma_free_coherent(dev, info->fix.smem_len, 1646 - buf, ch->dma_handle); 1533 + dma_free_coherent(dev, max_size, buf, ch->dma_handle); 1647 1534 return ret; 1648 1535 } 1649 1536 1537 + /* Initialize fixed screen information. Restrict pan to 2 lines steps 1538 + * for NV12 and NV21. 1539 + */ 1540 + info->fix = sh_mobile_lcdc_fix; 1650 1541 info->fix.smem_start = ch->dma_handle; 1651 - if (var->nonstd) 1542 + info->fix.smem_len = max_size; 1543 + if (cfg->fourcc == V4L2_PIX_FMT_NV12 || 1544 + cfg->fourcc == V4L2_PIX_FMT_NV21) 1545 + info->fix.ypanstep = 2; 1546 + 1547 + if (sh_mobile_format_is_yuv(var)) { 1652 1548 info->fix.line_length = var->xres; 1653 - else 1654 - info->fix.line_length = var->xres * (cfg->bpp / 8); 1549 + info->fix.visual = FB_VISUAL_FOURCC; 1550 + } else { 1551 + info->fix.line_length = var->xres * var->bits_per_pixel / 8; 1552 + info->fix.visual = FB_VISUAL_TRUECOLOR; 1553 + } 1655 1554 1656 1555 info->screen_base = buf; 1657 1556 info->device = dev; ··· 1749 1626 goto err1; 1750 1627 } 1751 1628 1752 - /* for dual channel LCDC (MAIN + SUB) force shared bpp setting */ 1629 + /* for dual channel LCDC (MAIN + SUB) force shared format setting */ 1753 1630 if (num_channels == 2) 1754 - priv->forced_bpp = pdata->ch[0].bpp; 1631 + priv->forced_fourcc = pdata->ch[0].fourcc; 1755 1632 1756 1633 priv->base = ioremap_nocache(res->start, resource_size(res)); 1757 1634 if (!priv->base) ··· 1798 1675 if (error < 0) 1799 1676 goto err1; 1800 1677 1801 - dev_info(info->dev, 1802 - "registered %s/%s as %dx%d %dbpp.\n", 1803 - pdev->name, 1804 - (ch->cfg.chan == LCDC_CHAN_MAINLCD) ? 1805 - "mainlcd" : "sublcd", 1806 - info->var.xres, info->var.yres, 1807 - ch->cfg.bpp); 1678 + dev_info(info->dev, "registered %s/%s as %dx%d %dbpp.\n", 1679 + pdev->name, (ch->cfg.chan == LCDC_CHAN_MAINLCD) ? 1680 + "mainlcd" : "sublcd", info->var.xres, info->var.yres, 1681 + info->var.bits_per_pixel); 1808 1682 1809 1683 /* deferred io mode: disable clock to save power */ 1810 1684 if (info->fbdefio || info->state == FBINFO_STATE_SUSPENDED) ··· 1829 1709 .remove = sh_mobile_lcdc_remove, 1830 1710 }; 1831 1711 1832 - static int __init sh_mobile_lcdc_init(void) 1833 - { 1834 - return platform_driver_register(&sh_mobile_lcdc_driver); 1835 - } 1836 - 1837 - static void __exit sh_mobile_lcdc_exit(void) 1838 - { 1839 - platform_driver_unregister(&sh_mobile_lcdc_driver); 1840 - } 1841 - 1842 - module_init(sh_mobile_lcdc_init); 1843 - module_exit(sh_mobile_lcdc_exit); 1712 + module_platform_driver(sh_mobile_lcdc_driver); 1844 1713 1845 1714 MODULE_DESCRIPTION("SuperH Mobile LCDC Framebuffer driver"); 1846 1715 MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
+1 -12
drivers/video/sh_mobile_meram.c
··· 679 679 .remove = sh_mobile_meram_remove, 680 680 }; 681 681 682 - static int __init sh_mobile_meram_init(void) 683 - { 684 - return platform_driver_register(&sh_mobile_meram_driver); 685 - } 686 - 687 - static void __exit sh_mobile_meram_exit(void) 688 - { 689 - platform_driver_unregister(&sh_mobile_meram_driver); 690 - } 691 - 692 - module_init(sh_mobile_meram_init); 693 - module_exit(sh_mobile_meram_exit); 682 + module_platform_driver(sh_mobile_meram_driver); 694 683 695 684 MODULE_DESCRIPTION("SuperH Mobile MERAM driver"); 696 685 MODULE_AUTHOR("Damian Hobson-Garcia / Takanari Hayama");
+1 -12
drivers/video/sm501fb.c
··· 2230 2230 }, 2231 2231 }; 2232 2232 2233 - static int __devinit sm501fb_init(void) 2234 - { 2235 - return platform_driver_register(&sm501fb_driver); 2236 - } 2237 - 2238 - static void __exit sm501fb_cleanup(void) 2239 - { 2240 - platform_driver_unregister(&sm501fb_driver); 2241 - } 2242 - 2243 - module_init(sm501fb_init); 2244 - module_exit(sm501fb_cleanup); 2233 + module_platform_driver(sm501fb_driver); 2245 2234 2246 2235 module_param_named(mode, fb_mode, charp, 0); 2247 2236 MODULE_PARM_DESC(mode,
+1 -12
drivers/video/vt8500lcdfb.c
··· 457 457 }, 458 458 }; 459 459 460 - static int __init vt8500lcd_init(void) 461 - { 462 - return platform_driver_register(&vt8500lcd_driver); 463 - } 464 - 465 - static void __exit vt8500lcd_exit(void) 466 - { 467 - platform_driver_unregister(&vt8500lcd_driver); 468 - } 469 - 470 - module_init(vt8500lcd_init); 471 - module_exit(vt8500lcd_exit); 460 + module_platform_driver(vt8500lcd_driver); 472 461 473 462 MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>"); 474 463 MODULE_DESCRIPTION("LCD controller driver for VIA VT8500");
+1 -12
drivers/video/w100fb.c
··· 1620 1620 }, 1621 1621 }; 1622 1622 1623 - int __init w100fb_init(void) 1624 - { 1625 - return platform_driver_register(&w100fb_driver); 1626 - } 1627 - 1628 - void __exit w100fb_cleanup(void) 1629 - { 1630 - platform_driver_unregister(&w100fb_driver); 1631 - } 1632 - 1633 - module_init(w100fb_init); 1634 - module_exit(w100fb_cleanup); 1623 + module_platform_driver(w100fb_driver); 1635 1624 1636 1625 MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver"); 1637 1626 MODULE_LICENSE("GPL");
+1 -12
drivers/video/wm8505fb.c
··· 404 404 }, 405 405 }; 406 406 407 - static int __init wm8505fb_init(void) 408 - { 409 - return platform_driver_register(&wm8505fb_driver); 410 - } 411 - 412 - static void __exit wm8505fb_exit(void) 413 - { 414 - platform_driver_unregister(&wm8505fb_driver); 415 - } 416 - 417 - module_init(wm8505fb_init); 418 - module_exit(wm8505fb_exit); 407 + module_platform_driver(wm8505fb_driver); 419 408 420 409 MODULE_AUTHOR("Ed Spiridonov <edo.rus@gmail.com>"); 421 410 MODULE_DESCRIPTION("Framebuffer driver for WMT WM8505");
+1 -12
drivers/video/wmt_ge_rops.c
··· 167 167 }, 168 168 }; 169 169 170 - static int __init wmt_ge_rops_init(void) 171 - { 172 - return platform_driver_register(&wmt_ge_rops_driver); 173 - } 174 - 175 - static void __exit wmt_ge_rops_exit(void) 176 - { 177 - platform_driver_unregister(&wmt_ge_rops_driver); 178 - } 179 - 180 - module_init(wmt_ge_rops_init); 181 - module_exit(wmt_ge_rops_exit); 170 + module_platform_driver(wmt_ge_rops_driver); 182 171 183 172 MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com"); 184 173 MODULE_DESCRIPTION("Accelerators for raster operations using "
+1 -19
drivers/video/xilinxfb.c
··· 511 511 }, 512 512 }; 513 513 514 - 515 - /* --------------------------------------------------------------------- 516 - * Module setup and teardown 517 - */ 518 - 519 - static int __init 520 - xilinxfb_init(void) 521 - { 522 - return platform_driver_register(&xilinxfb_of_driver); 523 - } 524 - 525 - static void __exit 526 - xilinxfb_cleanup(void) 527 - { 528 - platform_driver_unregister(&xilinxfb_of_driver); 529 - } 530 - 531 - module_init(xilinxfb_init); 532 - module_exit(xilinxfb_cleanup); 514 + module_platform_driver(xilinxfb_of_driver); 533 515 534 516 MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>"); 535 517 MODULE_DESCRIPTION("Xilinx TFT frame buffer driver");
-61
include/linux/display.h
··· 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 - 28 - struct display_device; 29 - 30 - /* This structure defines all the properties of a Display. */ 31 - struct 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 - 41 - struct 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 - 53 - extern struct display_device *display_device_register(struct display_driver *driver, 54 - struct device *dev, void *devdata); 55 - extern void display_device_unregister(struct display_device *dev); 56 - 57 - extern 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
+10 -4
include/linux/fb.h
··· 45 45 #define FB_TYPE_INTERLEAVED_PLANES 2 /* Interleaved planes */ 46 46 #define FB_TYPE_TEXT 3 /* Text/attributes */ 47 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 50 #define FB_AUX_TEXT_MDA 0 /* Monochrome text */ 50 51 #define FB_AUX_TEXT_CGA 1 /* CGA/EGA/VGA Color text */ ··· 70 69 #define FB_VISUAL_PSEUDOCOLOR 3 /* Pseudo color (like atari) */ 71 70 #define FB_VISUAL_DIRECTCOLOR 4 /* Direct color */ 72 71 #define FB_VISUAL_STATIC_PSEUDOCOLOR 5 /* Pseudo color readonly */ 72 + #define FB_VISUAL_FOURCC 6 /* Visual identified by a V4L2 FOURCC */ 73 73 74 74 #define FB_ACCEL_NONE 0 /* no hardware accelerator */ 75 75 #define FB_ACCEL_ATARIBLITT 1 /* Atari Blitter */ ··· 156 154 157 155 #define FB_ACCEL_PUV3_UNIGFX 0xa0 /* PKUnity-v3 Unigfx */ 158 156 157 + #define FB_CAP_FOURCC 1 /* Device supports FOURCC-based formats */ 158 + 159 159 struct fb_fix_screeninfo { 160 160 char id[16]; /* identification string eg "TT Builtin" */ 161 161 unsigned long smem_start; /* Start of frame buffer mem */ ··· 175 171 __u32 mmio_len; /* Length of Memory Mapped I/O */ 176 172 __u32 accel; /* Indicate to driver which */ 177 173 /* specific chip/card we have */ 178 - __u16 reserved[3]; /* Reserved for future compatibility */ 174 + __u16 capabilities; /* see FB_CAP_* */ 175 + __u16 reserved[2]; /* Reserved for future compatibility */ 179 176 }; 180 177 181 178 /* Interpretation of offset for color fields: All offsets are from the right, ··· 251 246 __u32 yoffset; /* resolution */ 252 247 253 248 __u32 bits_per_pixel; /* guess what */ 254 - __u32 grayscale; /* != 0 Graylevels instead of colors */ 255 - 249 + __u32 grayscale; /* 0 = color, 1 = grayscale, */ 250 + /* >1 = FOURCC */ 256 251 struct fb_bitfield red; /* bitfield in fb mem if true color, */ 257 252 struct fb_bitfield green; /* else only length is significant */ 258 253 struct fb_bitfield blue; ··· 278 273 __u32 sync; /* see FB_SYNC_* */ 279 274 __u32 vmode; /* see FB_VMODE_* */ 280 275 __u32 rotate; /* angle we rotate counter clockwise */ 281 - __u32 reserved[5]; /* Reserved for future compatibility */ 276 + __u32 colorspace; /* colorspace for FOURCC-based modes */ 277 + __u32 reserved[4]; /* Reserved for future compatibility */ 282 278 }; 283 279 284 280 struct fb_cmap {
+2
include/linux/videodev2.h
··· 343 343 #define V4L2_PIX_FMT_NV21 v4l2_fourcc('N', 'V', '2', '1') /* 12 Y/CrCb 4:2:0 */ 344 344 #define V4L2_PIX_FMT_NV16 v4l2_fourcc('N', 'V', '1', '6') /* 16 Y/CbCr 4:2:2 */ 345 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 349 /* two non contiguous planes - one Y, one Cr + Cb interleaved */ 348 350 #define V4L2_PIX_FMT_NV12M v4l2_fourcc('N', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 */
+2 -2
include/linux/zorro_ids.h
··· 360 360 #define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM ZORRO_ID(VILLAGE_TRONIC, 0x0B, 0) 361 361 #define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG ZORRO_ID(VILLAGE_TRONIC, 0x0C, 0) 362 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) 364 - #define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_MEM2 ZORRO_ID(VILLAGE_TRONIC, 0x16, 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_RAM2 ZORRO_ID(VILLAGE_TRONIC, 0x16, 0) 365 365 #define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_REG ZORRO_ID(VILLAGE_TRONIC, 0x17, 0) 366 366 #define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3 ZORRO_ID(VILLAGE_TRONIC, 0x18, 0) 367 367 #define ZORRO_PROD_VILLAGE_TRONIC_ARIADNE ZORRO_ID(VILLAGE_TRONIC, 0xC9, 0)
+34 -24
include/video/omapdss.h
··· 200 200 OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI, /* OMAP4: PLL2_CLK2 */ 201 201 }; 202 202 203 + enum omap_hdmi_flags { 204 + OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP = 1 << 0, 205 + }; 206 + 203 207 /* RFBI */ 204 208 205 209 struct rfbi_timings { ··· 298 294 u16 len); 299 295 int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel); 300 296 int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel); 301 - int dsi_video_mode_enable(struct omap_dss_device *dssdev, int channel); 302 - void dsi_video_mode_disable(struct omap_dss_device *dssdev, int channel); 297 + int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel); 298 + void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel); 303 299 304 300 /* Board specific data */ 305 301 struct omap_dss_board_info { ··· 313 309 314 310 /* Init with the board info */ 315 311 extern int omap_display_init(struct omap_dss_board_info *board_data); 312 + /* HDMI mux init*/ 313 + extern int omap_hdmi_init(enum omap_hdmi_flags flags); 316 314 317 315 struct omap_display_platform_data { 318 316 struct omap_dss_board_info *board_data; ··· 358 352 }; 359 353 360 354 struct omap_overlay_info { 361 - bool enabled; 362 - 363 355 u32 paddr; 364 356 u32 p_uv_addr; /* for NV12 format */ 365 357 u16 screen_width; ··· 389 385 390 386 /* dynamic fields */ 391 387 struct omap_overlay_manager *manager; 392 - struct omap_overlay_info info; 393 388 394 - bool manager_changed; 395 - /* if true, info has been changed, but not applied() yet */ 396 - bool info_dirty; 389 + /* 390 + * The following functions do not block: 391 + * 392 + * is_enabled 393 + * set_overlay_info 394 + * get_overlay_info 395 + * 396 + * The rest of the functions may block and cannot be called from 397 + * interrupt context 398 + */ 399 + 400 + int (*enable)(struct omap_overlay *ovl); 401 + int (*disable)(struct omap_overlay *ovl); 402 + bool (*is_enabled)(struct omap_overlay *ovl); 397 403 398 404 int (*set_manager)(struct omap_overlay *ovl, 399 405 struct omap_overlay_manager *mgr); ··· 432 418 433 419 struct omap_overlay_manager { 434 420 struct kobject kobj; 435 - struct list_head list; 436 421 437 422 /* static fields */ 438 423 const char *name; 439 424 enum omap_channel id; 440 425 enum omap_overlay_manager_caps caps; 441 - int num_overlays; 442 - struct omap_overlay **overlays; 426 + struct list_head overlays; 443 427 enum omap_display_type supported_displays; 444 428 445 429 /* dynamic fields */ 446 430 struct omap_dss_device *device; 447 - struct omap_overlay_manager_info info; 448 431 449 - bool device_changed; 450 - /* if true, info has been changed but not applied() yet */ 451 - bool info_dirty; 432 + /* 433 + * The following functions do not block: 434 + * 435 + * set_manager_info 436 + * get_manager_info 437 + * apply 438 + * 439 + * The rest of the functions may block and cannot be called from 440 + * interrupt context 441 + */ 452 442 453 443 int (*set_device)(struct omap_overlay_manager *mgr, 454 444 struct omap_dss_device *dssdev); ··· 466 448 int (*apply)(struct omap_overlay_manager *mgr); 467 449 int (*wait_for_go)(struct omap_overlay_manager *mgr); 468 450 int (*wait_for_vsync)(struct omap_overlay_manager *mgr); 469 - 470 - int (*enable)(struct omap_overlay_manager *mgr); 471 - int (*disable)(struct omap_overlay_manager *mgr); 472 451 }; 473 452 474 453 struct omap_dss_device { ··· 677 662 bool enable); 678 663 int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable); 679 664 680 - int omap_dsi_prepare_update(struct omap_dss_device *dssdev, 681 - u16 *x, u16 *y, u16 *w, u16 *h, 682 - bool enlarge_update_area); 683 - int omap_dsi_update(struct omap_dss_device *dssdev, 684 - int channel, 685 - u16 x, u16 y, u16 w, u16 h, 665 + int omap_dsi_update(struct omap_dss_device *dssdev, int channel, 686 666 void (*callback)(int, void *), void *data); 687 667 int omap_dsi_request_vc(struct omap_dss_device *dssdev, int *channel); 688 668 int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id);
+20 -1
include/video/sh_mipi_dsi.h
··· 28 28 struct sh_mobile_lcdc_chan_cfg; 29 29 30 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 33 48 struct sh_mipi_dsi_info { 34 49 enum sh_mipi_dsi_data_fmt data_format; 35 50 struct sh_mobile_lcdc_chan_cfg *lcd_chan; 51 + int lane; 36 52 unsigned long flags; 37 53 u32 clksrc; 38 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 60 #endif
+2 -2
include/video/sh_mobile_lcdc.h
··· 174 174 175 175 struct sh_mobile_lcdc_chan_cfg { 176 176 int chan; 177 - int bpp; 177 + int fourcc; 178 + int colorspace; 178 179 int interface_type; /* selects RGBn or SYSn I/F, see above */ 179 180 int clock_divider; 180 181 unsigned long flags; /* LCDC_FLAGS_... */ ··· 185 184 struct sh_mobile_lcdc_board_cfg board_cfg; 186 185 struct sh_mobile_lcdc_bl_info bl_info; 187 186 struct sh_mobile_lcdc_sys_bus_cfg sys_bus_cfg; /* only for SYSn I/F */ 188 - int nonstd; 189 187 struct sh_mobile_meram_cfg *meram_cfg; 190 188 }; 191 189