mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
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 ...
This commit is contained in:
commit
51be08419d
102 changed files with 6369 additions and 5553 deletions
121
Documentation/DocBook/media/v4l/pixfmt-nv24.xml
Normal file
121
Documentation/DocBook/media/v4l/pixfmt-nv24.xml
Normal file
|
@ -0,0 +1,121 @@
|
|||
<refentry>
|
||||
<refmeta>
|
||||
<refentrytitle>V4L2_PIX_FMT_NV24 ('NV24'), V4L2_PIX_FMT_NV42 ('NV42')</refentrytitle>
|
||||
&manvol;
|
||||
</refmeta>
|
||||
<refnamediv>
|
||||
<refname id="V4L2-PIX-FMT-NV24"><constant>V4L2_PIX_FMT_NV24</constant></refname>
|
||||
<refname id="V4L2-PIX-FMT-NV42"><constant>V4L2_PIX_FMT_NV42</constant></refname>
|
||||
<refpurpose>Formats with full horizontal and vertical
|
||||
chroma resolutions, also known as YUV 4:4:4. One luminance and one
|
||||
chrominance plane with alternating chroma samples as opposed to
|
||||
<constant>V4L2_PIX_FMT_YVU420</constant></refpurpose>
|
||||
</refnamediv>
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para>These are two-plane versions of the YUV 4:4:4 format. The three
|
||||
components are separated into two sub-images or planes. The Y plane is
|
||||
first, with each Y sample stored in one byte per pixel. For
|
||||
<constant>V4L2_PIX_FMT_NV24</constant>, a combined CbCr plane
|
||||
immediately follows the Y plane in memory. The CbCr plane has the same
|
||||
width and height, in pixels, as the Y plane (and the image). Each line
|
||||
contains one CbCr pair per pixel, with each Cb and Cr sample stored in
|
||||
one byte. <constant>V4L2_PIX_FMT_NV42</constant> is the same except that
|
||||
the Cb and Cr samples are swapped, the CrCb plane starts with a Cr
|
||||
sample.</para>
|
||||
|
||||
<para>If the Y plane has pad bytes after each row, then the CbCr plane
|
||||
has twice as many pad bytes after its rows.</para>
|
||||
|
||||
<example>
|
||||
<title><constant>V4L2_PIX_FMT_NV24</constant> 4 × 4
|
||||
pixel image</title>
|
||||
|
||||
<formalpara>
|
||||
<title>Byte Order.</title>
|
||||
<para>Each cell is one byte.
|
||||
<informaltable frame="none">
|
||||
<tgroup cols="9" align="center">
|
||||
<colspec align="left" colwidth="2*" />
|
||||
<tbody valign="top">
|
||||
<row>
|
||||
<entry>start + 0:</entry>
|
||||
<entry>Y'<subscript>00</subscript></entry>
|
||||
<entry>Y'<subscript>01</subscript></entry>
|
||||
<entry>Y'<subscript>02</subscript></entry>
|
||||
<entry>Y'<subscript>03</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start + 4:</entry>
|
||||
<entry>Y'<subscript>10</subscript></entry>
|
||||
<entry>Y'<subscript>11</subscript></entry>
|
||||
<entry>Y'<subscript>12</subscript></entry>
|
||||
<entry>Y'<subscript>13</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start + 8:</entry>
|
||||
<entry>Y'<subscript>20</subscript></entry>
|
||||
<entry>Y'<subscript>21</subscript></entry>
|
||||
<entry>Y'<subscript>22</subscript></entry>
|
||||
<entry>Y'<subscript>23</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start + 12:</entry>
|
||||
<entry>Y'<subscript>30</subscript></entry>
|
||||
<entry>Y'<subscript>31</subscript></entry>
|
||||
<entry>Y'<subscript>32</subscript></entry>
|
||||
<entry>Y'<subscript>33</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start + 16:</entry>
|
||||
<entry>Cb<subscript>00</subscript></entry>
|
||||
<entry>Cr<subscript>00</subscript></entry>
|
||||
<entry>Cb<subscript>01</subscript></entry>
|
||||
<entry>Cr<subscript>01</subscript></entry>
|
||||
<entry>Cb<subscript>02</subscript></entry>
|
||||
<entry>Cr<subscript>02</subscript></entry>
|
||||
<entry>Cb<subscript>03</subscript></entry>
|
||||
<entry>Cr<subscript>03</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start + 24:</entry>
|
||||
<entry>Cb<subscript>10</subscript></entry>
|
||||
<entry>Cr<subscript>10</subscript></entry>
|
||||
<entry>Cb<subscript>11</subscript></entry>
|
||||
<entry>Cr<subscript>11</subscript></entry>
|
||||
<entry>Cb<subscript>12</subscript></entry>
|
||||
<entry>Cr<subscript>12</subscript></entry>
|
||||
<entry>Cb<subscript>13</subscript></entry>
|
||||
<entry>Cr<subscript>13</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start + 32:</entry>
|
||||
<entry>Cb<subscript>20</subscript></entry>
|
||||
<entry>Cr<subscript>20</subscript></entry>
|
||||
<entry>Cb<subscript>21</subscript></entry>
|
||||
<entry>Cr<subscript>21</subscript></entry>
|
||||
<entry>Cb<subscript>22</subscript></entry>
|
||||
<entry>Cr<subscript>22</subscript></entry>
|
||||
<entry>Cb<subscript>23</subscript></entry>
|
||||
<entry>Cr<subscript>23</subscript></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>start + 40:</entry>
|
||||
<entry>Cb<subscript>30</subscript></entry>
|
||||
<entry>Cr<subscript>30</subscript></entry>
|
||||
<entry>Cb<subscript>31</subscript></entry>
|
||||
<entry>Cr<subscript>31</subscript></entry>
|
||||
<entry>Cb<subscript>32</subscript></entry>
|
||||
<entry>Cr<subscript>32</subscript></entry>
|
||||
<entry>Cb<subscript>33</subscript></entry>
|
||||
<entry>Cr<subscript>33</subscript></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
</formalpara>
|
||||
</example>
|
||||
</refsect1>
|
||||
</refentry>
|
|
@ -714,6 +714,7 @@ information.</para>
|
|||
&sub-nv12m;
|
||||
&sub-nv12mt;
|
||||
&sub-nv16;
|
||||
&sub-nv24;
|
||||
&sub-m420;
|
||||
</section>
|
||||
|
||||
|
|
306
Documentation/fb/api.txt
Normal file
306
Documentation/fb/api.txt
Normal file
|
@ -0,0 +1,306 @@
|
|||
The Frame Buffer Device API
|
||||
---------------------------
|
||||
|
||||
Last revised: June 21, 2011
|
||||
|
||||
|
||||
0. Introduction
|
||||
---------------
|
||||
|
||||
This document describes the frame buffer API used by applications to interact
|
||||
with frame buffer devices. In-kernel APIs between device drivers and the frame
|
||||
buffer core are not described.
|
||||
|
||||
Due to a lack of documentation in the original frame buffer API, drivers
|
||||
behaviours differ in subtle (and not so subtle) ways. This document describes
|
||||
the recommended API implementation, but applications should be prepared to
|
||||
deal with different behaviours.
|
||||
|
||||
|
||||
1. Capabilities
|
||||
---------------
|
||||
|
||||
Device and driver capabilities are reported in the fixed screen information
|
||||
capabilities field.
|
||||
|
||||
struct fb_fix_screeninfo {
|
||||
...
|
||||
__u16 capabilities; /* see FB_CAP_* */
|
||||
...
|
||||
};
|
||||
|
||||
Application should use those capabilities to find out what features they can
|
||||
expect from the device and driver.
|
||||
|
||||
- FB_CAP_FOURCC
|
||||
|
||||
The driver supports the four character code (FOURCC) based format setting API.
|
||||
When supported, formats are configured using a FOURCC instead of manually
|
||||
specifying color components layout.
|
||||
|
||||
|
||||
2. Types and visuals
|
||||
--------------------
|
||||
|
||||
Pixels are stored in memory in hardware-dependent formats. Applications need
|
||||
to be aware of the pixel storage format in order to write image data to the
|
||||
frame buffer memory in the format expected by the hardware.
|
||||
|
||||
Formats are described by frame buffer types and visuals. Some visuals require
|
||||
additional information, which are stored in the variable screen information
|
||||
bits_per_pixel, grayscale, red, green, blue and transp fields.
|
||||
|
||||
Visuals describe how color information is encoded and assembled to create
|
||||
macropixels. Types describe how macropixels are stored in memory. The following
|
||||
types and visuals are supported.
|
||||
|
||||
- FB_TYPE_PACKED_PIXELS
|
||||
|
||||
Macropixels are stored contiguously in a single plane. If the number of bits
|
||||
per macropixel is not a multiple of 8, whether macropixels are padded to the
|
||||
next multiple of 8 bits or packed together into bytes depends on the visual.
|
||||
|
||||
Padding at end of lines may be present and is then reported through the fixed
|
||||
screen information line_length field.
|
||||
|
||||
- FB_TYPE_PLANES
|
||||
|
||||
Macropixels are split across multiple planes. The number of planes is equal to
|
||||
the number of bits per macropixel, with plane i'th storing i'th bit from all
|
||||
macropixels.
|
||||
|
||||
Planes are located contiguously in memory.
|
||||
|
||||
- FB_TYPE_INTERLEAVED_PLANES
|
||||
|
||||
Macropixels are split across multiple planes. The number of planes is equal to
|
||||
the number of bits per macropixel, with plane i'th storing i'th bit from all
|
||||
macropixels.
|
||||
|
||||
Planes are interleaved in memory. The interleave factor, defined as the
|
||||
distance in bytes between the beginning of two consecutive interleaved blocks
|
||||
belonging to different planes, is stored in the fixed screen information
|
||||
type_aux field.
|
||||
|
||||
- FB_TYPE_FOURCC
|
||||
|
||||
Macropixels are stored in memory as described by the format FOURCC identifier
|
||||
stored in the variable screen information grayscale field.
|
||||
|
||||
- FB_VISUAL_MONO01
|
||||
|
||||
Pixels are black or white and stored on a number of bits (typically one)
|
||||
specified by the variable screen information bpp field.
|
||||
|
||||
Black pixels are represented by all bits set to 1 and white pixels by all bits
|
||||
set to 0. When the number of bits per pixel is smaller than 8, several pixels
|
||||
are packed together in a byte.
|
||||
|
||||
FB_VISUAL_MONO01 is currently used with FB_TYPE_PACKED_PIXELS only.
|
||||
|
||||
- FB_VISUAL_MONO10
|
||||
|
||||
Pixels are black or white and stored on a number of bits (typically one)
|
||||
specified by the variable screen information bpp field.
|
||||
|
||||
Black pixels are represented by all bits set to 0 and white pixels by all bits
|
||||
set to 1. When the number of bits per pixel is smaller than 8, several pixels
|
||||
are packed together in a byte.
|
||||
|
||||
FB_VISUAL_MONO01 is currently used with FB_TYPE_PACKED_PIXELS only.
|
||||
|
||||
- FB_VISUAL_TRUECOLOR
|
||||
|
||||
Pixels are broken into red, green and blue components, and each component
|
||||
indexes a read-only lookup table for the corresponding value. Lookup tables
|
||||
are device-dependent, and provide linear or non-linear ramps.
|
||||
|
||||
Each component is stored in a macropixel according to the variable screen
|
||||
information red, green, blue and transp fields.
|
||||
|
||||
- FB_VISUAL_PSEUDOCOLOR and FB_VISUAL_STATIC_PSEUDOCOLOR
|
||||
|
||||
Pixel values are encoded as indices into a colormap that stores red, green and
|
||||
blue components. The colormap is read-only for FB_VISUAL_STATIC_PSEUDOCOLOR
|
||||
and read-write for FB_VISUAL_PSEUDOCOLOR.
|
||||
|
||||
Each pixel value is stored in the number of bits reported by the variable
|
||||
screen information bits_per_pixel field.
|
||||
|
||||
- FB_VISUAL_DIRECTCOLOR
|
||||
|
||||
Pixels are broken into red, green and blue components, and each component
|
||||
indexes a programmable lookup table for the corresponding value.
|
||||
|
||||
Each component is stored in a macropixel according to the variable screen
|
||||
information red, green, blue and transp fields.
|
||||
|
||||
- FB_VISUAL_FOURCC
|
||||
|
||||
Pixels are encoded and interpreted as described by the format FOURCC
|
||||
identifier stored in the variable screen information grayscale field.
|
||||
|
||||
|
||||
3. Screen information
|
||||
---------------------
|
||||
|
||||
Screen information are queried by applications using the FBIOGET_FSCREENINFO
|
||||
and FBIOGET_VSCREENINFO ioctls. Those ioctls take a pointer to a
|
||||
fb_fix_screeninfo and fb_var_screeninfo structure respectively.
|
||||
|
||||
struct fb_fix_screeninfo stores device independent unchangeable information
|
||||
about the frame buffer device and the current format. Those information can't
|
||||
be directly modified by applications, but can be changed by the driver when an
|
||||
application modifies the format.
|
||||
|
||||
struct fb_fix_screeninfo {
|
||||
char id[16]; /* identification string eg "TT Builtin" */
|
||||
unsigned long smem_start; /* Start of frame buffer mem */
|
||||
/* (physical address) */
|
||||
__u32 smem_len; /* Length of frame buffer mem */
|
||||
__u32 type; /* see FB_TYPE_* */
|
||||
__u32 type_aux; /* Interleave for interleaved Planes */
|
||||
__u32 visual; /* see FB_VISUAL_* */
|
||||
__u16 xpanstep; /* zero if no hardware panning */
|
||||
__u16 ypanstep; /* zero if no hardware panning */
|
||||
__u16 ywrapstep; /* zero if no hardware ywrap */
|
||||
__u32 line_length; /* length of a line in bytes */
|
||||
unsigned long mmio_start; /* Start of Memory Mapped I/O */
|
||||
/* (physical address) */
|
||||
__u32 mmio_len; /* Length of Memory Mapped I/O */
|
||||
__u32 accel; /* Indicate to driver which */
|
||||
/* specific chip/card we have */
|
||||
__u16 capabilities; /* see FB_CAP_* */
|
||||
__u16 reserved[2]; /* Reserved for future compatibility */
|
||||
};
|
||||
|
||||
struct fb_var_screeninfo stores device independent changeable information
|
||||
about a frame buffer device, its current format and video mode, as well as
|
||||
other miscellaneous parameters.
|
||||
|
||||
struct fb_var_screeninfo {
|
||||
__u32 xres; /* visible resolution */
|
||||
__u32 yres;
|
||||
__u32 xres_virtual; /* virtual resolution */
|
||||
__u32 yres_virtual;
|
||||
__u32 xoffset; /* offset from virtual to visible */
|
||||
__u32 yoffset; /* resolution */
|
||||
|
||||
__u32 bits_per_pixel; /* guess what */
|
||||
__u32 grayscale; /* 0 = color, 1 = grayscale, */
|
||||
/* >1 = FOURCC */
|
||||
struct fb_bitfield red; /* bitfield in fb mem if true color, */
|
||||
struct fb_bitfield green; /* else only length is significant */
|
||||
struct fb_bitfield blue;
|
||||
struct fb_bitfield transp; /* transparency */
|
||||
|
||||
__u32 nonstd; /* != 0 Non standard pixel format */
|
||||
|
||||
__u32 activate; /* see FB_ACTIVATE_* */
|
||||
|
||||
__u32 height; /* height of picture in mm */
|
||||
__u32 width; /* width of picture in mm */
|
||||
|
||||
__u32 accel_flags; /* (OBSOLETE) see fb_info.flags */
|
||||
|
||||
/* Timing: All values in pixclocks, except pixclock (of course) */
|
||||
__u32 pixclock; /* pixel clock in ps (pico seconds) */
|
||||
__u32 left_margin; /* time from sync to picture */
|
||||
__u32 right_margin; /* time from picture to sync */
|
||||
__u32 upper_margin; /* time from sync to picture */
|
||||
__u32 lower_margin;
|
||||
__u32 hsync_len; /* length of horizontal sync */
|
||||
__u32 vsync_len; /* length of vertical sync */
|
||||
__u32 sync; /* see FB_SYNC_* */
|
||||
__u32 vmode; /* see FB_VMODE_* */
|
||||
__u32 rotate; /* angle we rotate counter clockwise */
|
||||
__u32 colorspace; /* colorspace for FOURCC-based modes */
|
||||
__u32 reserved[4]; /* Reserved for future compatibility */
|
||||
};
|
||||
|
||||
To modify variable information, applications call the FBIOPUT_VSCREENINFO
|
||||
ioctl with a pointer to a fb_var_screeninfo structure. If the call is
|
||||
successful, the driver will update the fixed screen information accordingly.
|
||||
|
||||
Instead of filling the complete fb_var_screeninfo structure manually,
|
||||
applications should call the FBIOGET_VSCREENINFO ioctl and modify only the
|
||||
fields they care about.
|
||||
|
||||
|
||||
4. Format configuration
|
||||
-----------------------
|
||||
|
||||
Frame buffer devices offer two ways to configure the frame buffer format: the
|
||||
legacy API and the FOURCC-based API.
|
||||
|
||||
|
||||
The legacy API has been the only frame buffer format configuration API for a
|
||||
long time and is thus widely used by application. It is the recommended API
|
||||
for applications when using RGB and grayscale formats, as well as legacy
|
||||
non-standard formats.
|
||||
|
||||
To select a format, applications set the fb_var_screeninfo bits_per_pixel field
|
||||
to the desired frame buffer depth. Values up to 8 will usually map to
|
||||
monochrome, grayscale or pseudocolor visuals, although this is not required.
|
||||
|
||||
- For grayscale formats, applications set the grayscale field to one. The red,
|
||||
blue, green and transp fields must be set to 0 by applications and ignored by
|
||||
drivers. Drivers must fill the red, blue and green offsets to 0 and lengths
|
||||
to the bits_per_pixel value.
|
||||
|
||||
- For pseudocolor formats, applications set the grayscale field to zero. The
|
||||
red, blue, green and transp fields must be set to 0 by applications and
|
||||
ignored by drivers. Drivers must fill the red, blue and green offsets to 0
|
||||
and lengths to the bits_per_pixel value.
|
||||
|
||||
- For truecolor and directcolor formats, applications set the grayscale field
|
||||
to zero, and the red, blue, green and transp fields to describe the layout of
|
||||
color components in memory.
|
||||
|
||||
struct fb_bitfield {
|
||||
__u32 offset; /* beginning of bitfield */
|
||||
__u32 length; /* length of bitfield */
|
||||
__u32 msb_right; /* != 0 : Most significant bit is */
|
||||
/* right */
|
||||
};
|
||||
|
||||
Pixel values are bits_per_pixel wide and are split in non-overlapping red,
|
||||
green, blue and alpha (transparency) components. Location and size of each
|
||||
component in the pixel value are described by the fb_bitfield offset and
|
||||
length fields. Offset are computed from the right.
|
||||
|
||||
Pixels are always stored in an integer number of bytes. If the number of
|
||||
bits per pixel is not a multiple of 8, pixel values are padded to the next
|
||||
multiple of 8 bits.
|
||||
|
||||
Upon successful format configuration, drivers update the fb_fix_screeninfo
|
||||
type, visual and line_length fields depending on the selected format.
|
||||
|
||||
|
||||
The FOURCC-based API replaces format descriptions by four character codes
|
||||
(FOURCC). FOURCCs are abstract identifiers that uniquely define a format
|
||||
without explicitly describing it. This is the only API that supports YUV
|
||||
formats. Drivers are also encouraged to implement the FOURCC-based API for RGB
|
||||
and grayscale formats.
|
||||
|
||||
Drivers that support the FOURCC-based API report this capability by setting
|
||||
the FB_CAP_FOURCC bit in the fb_fix_screeninfo capabilities field.
|
||||
|
||||
FOURCC definitions are located in the linux/videodev2.h header. However, and
|
||||
despite starting with the V4L2_PIX_FMT_prefix, they are not restricted to V4L2
|
||||
and don't require usage of the V4L2 subsystem. FOURCC documentation is
|
||||
available in Documentation/DocBook/v4l/pixfmt.xml.
|
||||
|
||||
To select a format, applications set the grayscale field to the desired FOURCC.
|
||||
For YUV formats, they should also select the appropriate colorspace by setting
|
||||
the colorspace field to one of the colorspaces listed in linux/videodev2.h and
|
||||
documented in Documentation/DocBook/v4l/colorspaces.xml.
|
||||
|
||||
The red, green, blue and transp fields are not used with the FOURCC-based API.
|
||||
For forward compatibility reasons applications must zero those fields, and
|
||||
drivers must ignore them. Values other than 0 may get a meaning in future
|
||||
extensions.
|
||||
|
||||
Upon successful format configuration, drivers update the fb_fix_screeninfo
|
||||
type, visual and line_length fields depending on the selected format. The type
|
||||
and visual fields are set to FB_TYPE_FOURCC and FB_VISUAL_FOURCC respectively.
|
|
@ -5669,6 +5669,12 @@ L: alsa-devel@alsa-project.org (moderated for non-subscribers)
|
|||
S: Supported
|
||||
F: sound/soc/samsung
|
||||
|
||||
SAMSUNG FRAMEBUFFER DRIVER
|
||||
M: Jingoo Han <jg1.han@samsung.com>
|
||||
L: linux-fbdev@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/video/s3c-fb.c
|
||||
|
||||
SERIAL DRIVERS
|
||||
M: Alan Cox <alan@linux.intel.com>
|
||||
L: linux-serial@vger.kernel.org
|
||||
|
|
|
@ -602,20 +602,6 @@ static void __init omap_sfh7741prox_init(void)
|
|||
__func__, OMAP4_SFH7741_ENABLE_GPIO, error);
|
||||
}
|
||||
|
||||
static void sdp4430_hdmi_mux_init(void)
|
||||
{
|
||||
/* PAD0_HDMI_HPD_PAD1_HDMI_CEC */
|
||||
omap_mux_init_signal("hdmi_hpd",
|
||||
OMAP_PIN_INPUT_PULLUP);
|
||||
omap_mux_init_signal("hdmi_cec",
|
||||
OMAP_PIN_INPUT_PULLUP);
|
||||
/* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */
|
||||
omap_mux_init_signal("hdmi_ddc_scl",
|
||||
OMAP_PIN_INPUT_PULLUP);
|
||||
omap_mux_init_signal("hdmi_ddc_sda",
|
||||
OMAP_PIN_INPUT_PULLUP);
|
||||
}
|
||||
|
||||
static struct gpio sdp4430_hdmi_gpios[] = {
|
||||
{ HDMI_GPIO_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_hpd" },
|
||||
{ HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" },
|
||||
|
@ -833,9 +819,16 @@ static void omap_4430sdp_display_init(void)
|
|||
pr_err("%s: Could not get display_sel GPIO\n", __func__);
|
||||
|
||||
sdp4430_lcd_init();
|
||||
sdp4430_hdmi_mux_init();
|
||||
sdp4430_picodlp_init();
|
||||
omap_display_init(&sdp4430_dss_data);
|
||||
/*
|
||||
* OMAP4460SDP/Blaze and OMAP4430 ES2.3 SDP/Blaze boards and
|
||||
* later have external pull up on the HDMI I2C lines
|
||||
*/
|
||||
if (cpu_is_omap446x() || omap_rev() > OMAP4430_REV_ES2_2)
|
||||
omap_hdmi_init(OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP);
|
||||
else
|
||||
omap_hdmi_init(0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OMAP_MUX
|
||||
|
|
|
@ -412,21 +412,6 @@ int __init omap4_panda_dvi_init(void)
|
|||
return r;
|
||||
}
|
||||
|
||||
|
||||
static void omap4_panda_hdmi_mux_init(void)
|
||||
{
|
||||
/* PAD0_HDMI_HPD_PAD1_HDMI_CEC */
|
||||
omap_mux_init_signal("hdmi_hpd",
|
||||
OMAP_PIN_INPUT_PULLUP);
|
||||
omap_mux_init_signal("hdmi_cec",
|
||||
OMAP_PIN_INPUT_PULLUP);
|
||||
/* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */
|
||||
omap_mux_init_signal("hdmi_ddc_scl",
|
||||
OMAP_PIN_INPUT_PULLUP);
|
||||
omap_mux_init_signal("hdmi_ddc_sda",
|
||||
OMAP_PIN_INPUT_PULLUP);
|
||||
}
|
||||
|
||||
static struct gpio panda_hdmi_gpios[] = {
|
||||
{ HDMI_GPIO_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_hpd" },
|
||||
{ HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" },
|
||||
|
@ -478,8 +463,16 @@ void omap4_panda_display_init(void)
|
|||
if (r)
|
||||
pr_err("error initializing panda DVI\n");
|
||||
|
||||
omap4_panda_hdmi_mux_init();
|
||||
omap_display_init(&omap4_panda_dss_data);
|
||||
|
||||
/*
|
||||
* OMAP4460SDP/Blaze and OMAP4430 ES2.3 SDP/Blaze boards and
|
||||
* later have external pull up on the HDMI I2C lines
|
||||
*/
|
||||
if (cpu_is_omap446x() || omap_rev() > OMAP4430_REV_ES2_2)
|
||||
omap_hdmi_init(OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP);
|
||||
else
|
||||
omap_hdmi_init(0);
|
||||
}
|
||||
|
||||
static void __init omap4_panda_init(void)
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <plat/omap-pm.h>
|
||||
#include "common.h"
|
||||
|
||||
#include "mux.h"
|
||||
#include "control.h"
|
||||
#include "display.h"
|
||||
|
||||
|
@ -97,6 +98,36 @@ static const struct omap_dss_hwmod_data omap4_dss_hwmod_data[] __initdata = {
|
|||
{ "dss_hdmi", "omapdss_hdmi", -1 },
|
||||
};
|
||||
|
||||
static void omap4_hdmi_mux_pads(enum omap_hdmi_flags flags)
|
||||
{
|
||||
u32 reg;
|
||||
u16 control_i2c_1;
|
||||
|
||||
/* PAD0_HDMI_HPD_PAD1_HDMI_CEC */
|
||||
omap_mux_init_signal("hdmi_hpd",
|
||||
OMAP_PIN_INPUT_PULLUP);
|
||||
omap_mux_init_signal("hdmi_cec",
|
||||
OMAP_PIN_INPUT_PULLUP);
|
||||
/* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */
|
||||
omap_mux_init_signal("hdmi_ddc_scl",
|
||||
OMAP_PIN_INPUT_PULLUP);
|
||||
omap_mux_init_signal("hdmi_ddc_sda",
|
||||
OMAP_PIN_INPUT_PULLUP);
|
||||
|
||||
/*
|
||||
* CONTROL_I2C_1: HDMI_DDC_SDA_PULLUPRESX (bit 28) and
|
||||
* HDMI_DDC_SCL_PULLUPRESX (bit 24) are set to disable
|
||||
* internal pull up resistor.
|
||||
*/
|
||||
if (flags & OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP) {
|
||||
control_i2c_1 = OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_1;
|
||||
reg = omap4_ctrl_pad_readl(control_i2c_1);
|
||||
reg |= (OMAP4_HDMI_DDC_SDA_PULLUPRESX_MASK |
|
||||
OMAP4_HDMI_DDC_SCL_PULLUPRESX_MASK);
|
||||
omap4_ctrl_pad_writel(reg, control_i2c_1);
|
||||
}
|
||||
}
|
||||
|
||||
static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
|
||||
{
|
||||
u32 enable_mask, enable_shift;
|
||||
|
@ -130,6 +161,14 @@ static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int omap_hdmi_init(enum omap_hdmi_flags flags)
|
||||
{
|
||||
if (cpu_is_omap44xx())
|
||||
omap4_hdmi_mux_pads(flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int omap_dsi_enable_pads(int dsi_id, unsigned lane_mask)
|
||||
{
|
||||
if (cpu_is_omap44xx())
|
||||
|
|
|
@ -271,7 +271,7 @@ static struct sh_mobile_lcdc_info lcdc0_info = {
|
|||
.flags = LCDC_FLAGS_DWPOL,
|
||||
.lcd_size_cfg.width = 44,
|
||||
.lcd_size_cfg.height = 79,
|
||||
.bpp = 16,
|
||||
.fourcc = V4L2_PIX_FMT_RGB565,
|
||||
.lcd_cfg = lcdc0_modes,
|
||||
.num_cfg = ARRAY_SIZE(lcdc0_modes),
|
||||
.board_cfg = {
|
||||
|
@ -321,12 +321,46 @@ static struct resource mipidsi0_resources[] = {
|
|||
},
|
||||
};
|
||||
|
||||
#define DSI0PHYCR 0xe615006c
|
||||
static int sh_mipi_set_dot_clock(struct platform_device *pdev,
|
||||
void __iomem *base,
|
||||
int enable)
|
||||
{
|
||||
struct clk *pck;
|
||||
int ret;
|
||||
|
||||
pck = clk_get(&pdev->dev, "dsip_clk");
|
||||
if (IS_ERR(pck)) {
|
||||
ret = PTR_ERR(pck);
|
||||
goto sh_mipi_set_dot_clock_pck_err;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
clk_set_rate(pck, clk_round_rate(pck, 24000000));
|
||||
__raw_writel(0x2a809010, DSI0PHYCR);
|
||||
clk_enable(pck);
|
||||
} else {
|
||||
clk_disable(pck);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
clk_put(pck);
|
||||
|
||||
sh_mipi_set_dot_clock_pck_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct sh_mipi_dsi_info mipidsi0_info = {
|
||||
.data_format = MIPI_RGB888,
|
||||
.lcd_chan = &lcdc0_info.ch[0],
|
||||
.lane = 2,
|
||||
.vsynw_offset = 20,
|
||||
.clksrc = 1,
|
||||
.flags = SH_MIPI_DSI_HSABM,
|
||||
.flags = SH_MIPI_DSI_HSABM |
|
||||
SH_MIPI_DSI_SYNC_PULSES_MODE |
|
||||
SH_MIPI_DSI_HSbyteCLK,
|
||||
.set_dot_clock = sh_mipi_set_dot_clock,
|
||||
};
|
||||
|
||||
static struct platform_device mipidsi0_device = {
|
||||
|
@ -472,8 +506,6 @@ static void __init ag5evm_map_io(void)
|
|||
shmobile_setup_console();
|
||||
}
|
||||
|
||||
#define DSI0PHYCR 0xe615006c
|
||||
|
||||
static void __init ag5evm_init(void)
|
||||
{
|
||||
sh73a0_pinmux_init();
|
||||
|
@ -554,9 +586,6 @@ static void __init ag5evm_init(void)
|
|||
gpio_direction_output(GPIO_PORT235, 0);
|
||||
lcd_backlight_reset();
|
||||
|
||||
/* MIPI-DSI clock setup */
|
||||
__raw_writel(0x2a809010, DSI0PHYCR);
|
||||
|
||||
/* enable SDHI0 on CN15 [SD I/F] */
|
||||
gpio_request(GPIO_FN_SDHICD0, NULL);
|
||||
gpio_request(GPIO_FN_SDHIWP0, NULL);
|
||||
|
|
|
@ -491,7 +491,7 @@ static struct sh_mobile_lcdc_info lcdc_info = {
|
|||
.meram_dev = &meram_info,
|
||||
.ch[0] = {
|
||||
.chan = LCDC_CHAN_MAINLCD,
|
||||
.bpp = 16,
|
||||
.fourcc = V4L2_PIX_FMT_RGB565,
|
||||
.lcd_cfg = ap4evb_lcdc_modes,
|
||||
.num_cfg = ARRAY_SIZE(ap4evb_lcdc_modes),
|
||||
.meram_cfg = &lcd_meram_cfg,
|
||||
|
@ -564,6 +564,30 @@ static struct platform_device keysc_device = {
|
|||
};
|
||||
|
||||
/* MIPI-DSI */
|
||||
#define PHYCTRL 0x0070
|
||||
static int sh_mipi_set_dot_clock(struct platform_device *pdev,
|
||||
void __iomem *base,
|
||||
int enable)
|
||||
{
|
||||
struct clk *pck = clk_get(&pdev->dev, "dsip_clk");
|
||||
void __iomem *phy = base + PHYCTRL;
|
||||
|
||||
if (IS_ERR(pck))
|
||||
return PTR_ERR(pck);
|
||||
|
||||
if (enable) {
|
||||
clk_set_rate(pck, clk_round_rate(pck, 24000000));
|
||||
iowrite32(ioread32(phy) | (0xb << 8), phy);
|
||||
clk_enable(pck);
|
||||
} else {
|
||||
clk_disable(pck);
|
||||
}
|
||||
|
||||
clk_put(pck);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct resource mipidsi0_resources[] = {
|
||||
[0] = {
|
||||
.start = 0xffc60000,
|
||||
|
@ -580,7 +604,11 @@ static struct resource mipidsi0_resources[] = {
|
|||
static struct sh_mipi_dsi_info mipidsi0_info = {
|
||||
.data_format = MIPI_RGB888,
|
||||
.lcd_chan = &lcdc_info.ch[0],
|
||||
.lane = 2,
|
||||
.vsynw_offset = 17,
|
||||
.flags = SH_MIPI_DSI_SYNC_PULSES_MODE |
|
||||
SH_MIPI_DSI_HSbyteCLK,
|
||||
.set_dot_clock = sh_mipi_set_dot_clock,
|
||||
};
|
||||
|
||||
static struct platform_device mipidsi0_device = {
|
||||
|
@ -798,7 +826,7 @@ static struct sh_mobile_lcdc_info sh_mobile_lcdc1_info = {
|
|||
.meram_dev = &meram_info,
|
||||
.ch[0] = {
|
||||
.chan = LCDC_CHAN_MAINLCD,
|
||||
.bpp = 16,
|
||||
.fourcc = V4L2_PIX_FMT_RGB565,
|
||||
.interface_type = RGB24,
|
||||
.clock_divider = 1,
|
||||
.flags = LCDC_FLAGS_DWPOL,
|
||||
|
|
|
@ -388,7 +388,7 @@ static struct sh_mobile_lcdc_info lcdc_info = {
|
|||
.clock_source = LCDC_CLK_BUS,
|
||||
.ch[0] = {
|
||||
.chan = LCDC_CHAN_MAINLCD,
|
||||
.bpp = 16,
|
||||
.fourcc = V4L2_PIX_FMT_RGB565,
|
||||
.lcd_cfg = mackerel_lcdc_modes,
|
||||
.num_cfg = ARRAY_SIZE(mackerel_lcdc_modes),
|
||||
.interface_type = RGB24,
|
||||
|
@ -451,7 +451,7 @@ static struct sh_mobile_lcdc_info hdmi_lcdc_info = {
|
|||
.clock_source = LCDC_CLK_EXTERNAL,
|
||||
.ch[0] = {
|
||||
.chan = LCDC_CHAN_MAINLCD,
|
||||
.bpp = 16,
|
||||
.fourcc = V4L2_PIX_FMT_RGB565,
|
||||
.interface_type = RGB24,
|
||||
.clock_divider = 1,
|
||||
.flags = LCDC_FLAGS_DWPOL,
|
||||
|
|
|
@ -612,8 +612,8 @@ static struct clk_lookup lookups[] = {
|
|||
CLKDEV_CON_ID("hdmi_clk", &div6_reparent_clks[DIV6_HDMI]),
|
||||
CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]),
|
||||
CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSIT]),
|
||||
CLKDEV_ICK_ID("dsi0p_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]),
|
||||
CLKDEV_ICK_ID("dsi1p_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]),
|
||||
CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]),
|
||||
CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]),
|
||||
|
||||
/* MSTP32 clocks */
|
||||
CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* IIC2 */
|
||||
|
|
|
@ -427,8 +427,8 @@ static struct clk_lookup lookups[] = {
|
|||
CLKDEV_CON_ID("sdhi2_clk", &div6_clks[DIV6_SDHI2]),
|
||||
CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]),
|
||||
CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSIT]),
|
||||
CLKDEV_ICK_ID("dsi0p_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]),
|
||||
CLKDEV_ICK_ID("dsi1p_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]),
|
||||
CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]),
|
||||
CLKDEV_ICK_ID("dsip_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSI1P]),
|
||||
|
||||
/* MSTP32 clocks */
|
||||
CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* I2C2 */
|
||||
|
|
|
@ -207,7 +207,7 @@ static struct sh_mobile_lcdc_info lcdc_info = {
|
|||
.clock_source = LCDC_CLK_EXTERNAL,
|
||||
.ch[0] = {
|
||||
.chan = LCDC_CHAN_MAINLCD,
|
||||
.bpp = 16,
|
||||
.fourcc = V4L2_PIX_FMT_RGB565,
|
||||
.interface_type = RGB18,
|
||||
.clock_divider = 1,
|
||||
.lcd_cfg = ap325rxa_lcdc_modes,
|
||||
|
|
|
@ -324,7 +324,7 @@ static struct sh_mobile_lcdc_info lcdc_info = {
|
|||
.ch[0] = {
|
||||
.interface_type = RGB18,
|
||||
.chan = LCDC_CHAN_MAINLCD,
|
||||
.bpp = 16,
|
||||
.fourcc = V4L2_PIX_FMT_RGB565,
|
||||
.lcd_size_cfg = { /* 7.0 inch */
|
||||
.width = 152,
|
||||
.height = 91,
|
||||
|
|
|
@ -143,7 +143,7 @@ static struct sh_mobile_lcdc_info kfr2r09_sh_lcdc_info = {
|
|||
.clock_source = LCDC_CLK_BUS,
|
||||
.ch[0] = {
|
||||
.chan = LCDC_CHAN_MAINLCD,
|
||||
.bpp = 16,
|
||||
.fourcc = V4L2_PIX_FMT_RGB565,
|
||||
.interface_type = SYS18,
|
||||
.clock_divider = 6,
|
||||
.flags = LCDC_FLAGS_DWPOL,
|
||||
|
|
|
@ -241,7 +241,7 @@ static struct sh_mobile_lcdc_info sh_mobile_lcdc_info = {
|
|||
.clock_source = LCDC_CLK_BUS,
|
||||
.ch[0] = {
|
||||
.chan = LCDC_CHAN_MAINLCD,
|
||||
.bpp = 16,
|
||||
.fourcc = V4L2_PIX_FMT_RGB565,
|
||||
.interface_type = RGB16,
|
||||
.clock_divider = 2,
|
||||
.lcd_cfg = migor_lcd_modes,
|
||||
|
@ -255,7 +255,7 @@ static struct sh_mobile_lcdc_info sh_mobile_lcdc_info = {
|
|||
.clock_source = LCDC_CLK_PERIPHERAL,
|
||||
.ch[0] = {
|
||||
.chan = LCDC_CHAN_MAINLCD,
|
||||
.bpp = 16,
|
||||
.fourcc = V4L2_PIX_FMT_RGB565,
|
||||
.interface_type = SYS16A,
|
||||
.clock_divider = 10,
|
||||
.lcd_cfg = migor_lcd_modes,
|
||||
|
|
|
@ -179,7 +179,7 @@ static struct sh_mobile_lcdc_info lcdc_info = {
|
|||
.clock_source = LCDC_CLK_EXTERNAL,
|
||||
.ch[0] = {
|
||||
.chan = LCDC_CHAN_MAINLCD,
|
||||
.bpp = 16,
|
||||
.fourcc = V4L2_PIX_FMT_RGB565,
|
||||
.clock_divider = 1,
|
||||
.lcd_size_cfg = { /* 7.0 inch */
|
||||
.width = 152,
|
||||
|
|
|
@ -424,7 +424,7 @@ static int omapvid_setup_overlay(struct omap_vout_device *vout,
|
|||
"%s enable=%d addr=%x width=%d\n height=%d color_mode=%d\n"
|
||||
"rotation=%d mirror=%d posx=%d posy=%d out_width = %d \n"
|
||||
"out_height=%d rotation_type=%d screen_width=%d\n",
|
||||
__func__, info.enabled, info.paddr, info.width, info.height,
|
||||
__func__, ovl->is_enabled(ovl), info.paddr, info.width, info.height,
|
||||
info.color_mode, info.rotation, info.mirror, info.pos_x,
|
||||
info.pos_y, info.out_width, info.out_height, info.rotation_type,
|
||||
info.screen_width);
|
||||
|
@ -943,12 +943,8 @@ static int omap_vout_release(struct file *file)
|
|||
/* Disable all the overlay managers connected with this interface */
|
||||
for (i = 0; i < ovid->num_overlays; i++) {
|
||||
struct omap_overlay *ovl = ovid->overlays[i];
|
||||
if (ovl->manager && ovl->manager->device) {
|
||||
struct omap_overlay_info info;
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
info.enabled = 0;
|
||||
ovl->set_overlay_info(ovl, &info);
|
||||
}
|
||||
if (ovl->manager && ovl->manager->device)
|
||||
ovl->disable(ovl);
|
||||
}
|
||||
/* Turn off the pipeline */
|
||||
ret = omapvid_apply_changes(vout);
|
||||
|
@ -1668,7 +1664,6 @@ static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
|
|||
if (ovl->manager && ovl->manager->device) {
|
||||
struct omap_overlay_info info;
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
info.enabled = 1;
|
||||
info.paddr = addr;
|
||||
if (ovl->set_overlay_info(ovl, &info)) {
|
||||
ret = -EINVAL;
|
||||
|
@ -1687,6 +1682,16 @@ static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
|
|||
if (ret)
|
||||
v4l2_err(&vout->vid_dev->v4l2_dev, "failed to change mode\n");
|
||||
|
||||
for (j = 0; j < ovid->num_overlays; j++) {
|
||||
struct omap_overlay *ovl = ovid->overlays[j];
|
||||
|
||||
if (ovl->manager && ovl->manager->device) {
|
||||
ret = ovl->enable(ovl);
|
||||
if (ret)
|
||||
goto streamon_err1;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
streamon_err1:
|
||||
|
@ -1716,16 +1721,8 @@ static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
|
|||
for (j = 0; j < ovid->num_overlays; j++) {
|
||||
struct omap_overlay *ovl = ovid->overlays[j];
|
||||
|
||||
if (ovl->manager && ovl->manager->device) {
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
info.enabled = 0;
|
||||
ret = ovl->set_overlay_info(ovl, &info);
|
||||
if (ret)
|
||||
v4l2_err(&vout->vid_dev->v4l2_dev,
|
||||
"failed to update overlay info in streamoff\n");
|
||||
}
|
||||
if (ovl->manager && ovl->manager->device)
|
||||
ovl->disable(ovl);
|
||||
}
|
||||
|
||||
/* Turn of the pipeline */
|
||||
|
|
|
@ -2413,7 +2413,6 @@ source "drivers/video/omap/Kconfig"
|
|||
source "drivers/video/omap2/Kconfig"
|
||||
|
||||
source "drivers/video/backlight/Kconfig"
|
||||
source "drivers/video/display/Kconfig"
|
||||
|
||||
if VT
|
||||
source "drivers/video/console/Kconfig"
|
||||
|
|
|
@ -13,7 +13,7 @@ fb-objs := $(fb-y)
|
|||
|
||||
obj-$(CONFIG_VT) += console/
|
||||
obj-$(CONFIG_LOGO) += logo/
|
||||
obj-y += backlight/ display/
|
||||
obj-y += backlight/
|
||||
|
||||
obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o
|
||||
obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -100,8 +100,11 @@ static int atmel_bl_update_status(struct backlight_device *bl)
|
|||
brightness = 0;
|
||||
|
||||
lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, brightness);
|
||||
lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR,
|
||||
if (contrast_ctr & ATMEL_LCDC_POL_POSITIVE)
|
||||
lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR,
|
||||
brightness ? contrast_ctr : 0);
|
||||
else
|
||||
lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr);
|
||||
|
||||
bl->props.fb_blank = bl->props.power = sinfo->bl_power = power;
|
||||
|
||||
|
@ -682,14 +685,30 @@ static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red,
|
|||
|
||||
case FB_VISUAL_PSEUDOCOLOR:
|
||||
if (regno < 256) {
|
||||
val = ((red >> 11) & 0x001f);
|
||||
val |= ((green >> 6) & 0x03e0);
|
||||
val |= ((blue >> 1) & 0x7c00);
|
||||
if (cpu_is_at91sam9261() || cpu_is_at91sam9263()
|
||||
|| cpu_is_at91sam9rl()) {
|
||||
/* old style I+BGR:555 */
|
||||
val = ((red >> 11) & 0x001f);
|
||||
val |= ((green >> 6) & 0x03e0);
|
||||
val |= ((blue >> 1) & 0x7c00);
|
||||
|
||||
/*
|
||||
* TODO: intensity bit. Maybe something like
|
||||
* ~(red[10] ^ green[10] ^ blue[10]) & 1
|
||||
*/
|
||||
/*
|
||||
* TODO: intensity bit. Maybe something like
|
||||
* ~(red[10] ^ green[10] ^ blue[10]) & 1
|
||||
*/
|
||||
} else {
|
||||
/* new style BGR:565 / RGB:565 */
|
||||
if (sinfo->lcd_wiring_mode ==
|
||||
ATMEL_LCDC_WIRING_RGB) {
|
||||
val = ((blue >> 11) & 0x001f);
|
||||
val |= ((red >> 0) & 0xf800);
|
||||
} else {
|
||||
val = ((red >> 11) & 0x001f);
|
||||
val |= ((blue >> 0) & 0xf800);
|
||||
}
|
||||
|
||||
val |= ((green >> 5) & 0x07e0);
|
||||
}
|
||||
|
||||
lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val);
|
||||
ret = 0;
|
||||
|
|
|
@ -280,52 +280,74 @@ MODULE_DEVICE_TABLE(pci, cirrusfb_pci_table);
|
|||
#endif /* CONFIG_PCI */
|
||||
|
||||
#ifdef CONFIG_ZORRO
|
||||
static const struct zorro_device_id cirrusfb_zorro_table[] = {
|
||||
struct zorrocl {
|
||||
enum cirrus_board type; /* Board type */
|
||||
u32 regoffset; /* Offset of registers in first Zorro device */
|
||||
u32 ramsize; /* Size of video RAM in first Zorro device */
|
||||
/* If zero, use autoprobe on RAM device */
|
||||
u32 ramoffset; /* Offset of video RAM in first Zorro device */
|
||||
zorro_id ramid; /* Zorro ID of RAM device */
|
||||
zorro_id ramid2; /* Zorro ID of optional second RAM device */
|
||||
};
|
||||
|
||||
static const struct zorrocl zcl_sd64 __devinitconst = {
|
||||
.type = BT_SD64,
|
||||
.ramid = ZORRO_PROD_HELFRICH_SD64_RAM,
|
||||
};
|
||||
|
||||
static const struct zorrocl zcl_piccolo __devinitconst = {
|
||||
.type = BT_PICCOLO,
|
||||
.ramid = ZORRO_PROD_HELFRICH_PICCOLO_RAM,
|
||||
};
|
||||
|
||||
static const struct zorrocl zcl_picasso __devinitconst = {
|
||||
.type = BT_PICASSO,
|
||||
.ramid = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
|
||||
};
|
||||
|
||||
static const struct zorrocl zcl_spectrum __devinitconst = {
|
||||
.type = BT_SPECTRUM,
|
||||
.ramid = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
|
||||
};
|
||||
|
||||
static const struct zorrocl zcl_picasso4_z3 __devinitconst = {
|
||||
.type = BT_PICASSO4,
|
||||
.regoffset = 0x00600000,
|
||||
.ramsize = 4 * MB_,
|
||||
.ramoffset = 0x01000000, /* 0x02000000 for 64 MiB boards */
|
||||
};
|
||||
|
||||
static const struct zorrocl zcl_picasso4_z2 __devinitconst = {
|
||||
.type = BT_PICASSO4,
|
||||
.regoffset = 0x10000,
|
||||
.ramid = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM1,
|
||||
.ramid2 = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM2,
|
||||
};
|
||||
|
||||
|
||||
static const struct zorro_device_id cirrusfb_zorro_table[] __devinitconst = {
|
||||
{
|
||||
.id = ZORRO_PROD_HELFRICH_SD64_RAM,
|
||||
.driver_data = BT_SD64,
|
||||
.id = ZORRO_PROD_HELFRICH_SD64_REG,
|
||||
.driver_data = (unsigned long)&zcl_sd64,
|
||||
}, {
|
||||
.id = ZORRO_PROD_HELFRICH_PICCOLO_RAM,
|
||||
.driver_data = BT_PICCOLO,
|
||||
.id = ZORRO_PROD_HELFRICH_PICCOLO_REG,
|
||||
.driver_data = (unsigned long)&zcl_piccolo,
|
||||
}, {
|
||||
.id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM,
|
||||
.driver_data = BT_PICASSO,
|
||||
.id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
|
||||
.driver_data = (unsigned long)&zcl_picasso,
|
||||
}, {
|
||||
.id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM,
|
||||
.driver_data = BT_SPECTRUM,
|
||||
.id = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
|
||||
.driver_data = (unsigned long)&zcl_spectrum,
|
||||
}, {
|
||||
.id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3,
|
||||
.driver_data = BT_PICASSO4,
|
||||
.driver_data = (unsigned long)&zcl_picasso4_z3,
|
||||
}, {
|
||||
.id = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_REG,
|
||||
.driver_data = (unsigned long)&zcl_picasso4_z2,
|
||||
},
|
||||
{ 0 }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(zorro, cirrusfb_zorro_table);
|
||||
|
||||
static const struct {
|
||||
zorro_id id2;
|
||||
unsigned long size;
|
||||
} cirrusfb_zorro_table2[] = {
|
||||
[BT_SD64] = {
|
||||
.id2 = ZORRO_PROD_HELFRICH_SD64_REG,
|
||||
.size = 0x400000
|
||||
},
|
||||
[BT_PICCOLO] = {
|
||||
.id2 = ZORRO_PROD_HELFRICH_PICCOLO_REG,
|
||||
.size = 0x200000
|
||||
},
|
||||
[BT_PICASSO] = {
|
||||
.id2 = ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG,
|
||||
.size = 0x200000
|
||||
},
|
||||
[BT_SPECTRUM] = {
|
||||
.id2 = ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG,
|
||||
.size = 0x200000
|
||||
},
|
||||
[BT_PICASSO4] = {
|
||||
.id2 = 0,
|
||||
.size = 0x400000
|
||||
}
|
||||
};
|
||||
#endif /* CONFIG_ZORRO */
|
||||
|
||||
#ifdef CIRRUSFB_DEBUG
|
||||
|
@ -1956,16 +1978,12 @@ static void cirrusfb_zorro_unmap(struct fb_info *info)
|
|||
struct cirrusfb_info *cinfo = info->par;
|
||||
struct zorro_dev *zdev = to_zorro_dev(info->device);
|
||||
|
||||
zorro_release_device(zdev);
|
||||
|
||||
if (cinfo->btype == BT_PICASSO4) {
|
||||
cinfo->regbase -= 0x600000;
|
||||
iounmap((void *)cinfo->regbase);
|
||||
if (info->fix.smem_start > 16 * MB_)
|
||||
iounmap(info->screen_base);
|
||||
} else {
|
||||
if (zorro_resource_start(zdev) > 0x01000000)
|
||||
iounmap(info->screen_base);
|
||||
}
|
||||
if (info->fix.mmio_start > 16 * MB_)
|
||||
iounmap(cinfo->regbase);
|
||||
|
||||
zorro_release_device(zdev);
|
||||
}
|
||||
#endif /* CONFIG_ZORRO */
|
||||
|
||||
|
@ -2222,115 +2240,116 @@ static struct pci_driver cirrusfb_pci_driver = {
|
|||
static int __devinit cirrusfb_zorro_register(struct zorro_dev *z,
|
||||
const struct zorro_device_id *ent)
|
||||
{
|
||||
struct cirrusfb_info *cinfo;
|
||||
struct fb_info *info;
|
||||
int error;
|
||||
const struct zorrocl *zcl;
|
||||
enum cirrus_board btype;
|
||||
struct zorro_dev *z2 = NULL;
|
||||
unsigned long board_addr, board_size, size;
|
||||
int ret;
|
||||
|
||||
btype = ent->driver_data;
|
||||
if (cirrusfb_zorro_table2[btype].id2)
|
||||
z2 = zorro_find_device(cirrusfb_zorro_table2[btype].id2, NULL);
|
||||
size = cirrusfb_zorro_table2[btype].size;
|
||||
unsigned long regbase, ramsize, rambase;
|
||||
struct cirrusfb_info *cinfo;
|
||||
|
||||
info = framebuffer_alloc(sizeof(struct cirrusfb_info), &z->dev);
|
||||
if (!info) {
|
||||
printk(KERN_ERR "cirrusfb: could not allocate memory\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_out;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dev_info(info->device, "%s board detected\n",
|
||||
cirrusfb_board_info[btype].name);
|
||||
zcl = (const struct zorrocl *)ent->driver_data;
|
||||
btype = zcl->type;
|
||||
regbase = zorro_resource_start(z) + zcl->regoffset;
|
||||
ramsize = zcl->ramsize;
|
||||
if (ramsize) {
|
||||
rambase = zorro_resource_start(z) + zcl->ramoffset;
|
||||
if (zorro_resource_len(z) == 64 * MB_) {
|
||||
/* Quirk for 64 MiB Picasso IV */
|
||||
rambase += zcl->ramoffset;
|
||||
}
|
||||
} else {
|
||||
struct zorro_dev *ram = zorro_find_device(zcl->ramid, NULL);
|
||||
if (!ram || !zorro_resource_len(ram)) {
|
||||
dev_err(info->device, "No video RAM found\n");
|
||||
error = -ENODEV;
|
||||
goto err_release_fb;
|
||||
}
|
||||
rambase = zorro_resource_start(ram);
|
||||
ramsize = zorro_resource_len(ram);
|
||||
if (zcl->ramid2 &&
|
||||
(ram = zorro_find_device(zcl->ramid2, NULL))) {
|
||||
if (zorro_resource_start(ram) != rambase + ramsize) {
|
||||
dev_warn(info->device,
|
||||
"Skipping non-contiguous RAM at %pR\n",
|
||||
&ram->resource);
|
||||
} else {
|
||||
ramsize += zorro_resource_len(ram);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dev_info(info->device,
|
||||
"%s board detected, REG at 0x%lx, %lu MiB RAM at 0x%lx\n",
|
||||
cirrusfb_board_info[btype].name, regbase, ramsize / MB_,
|
||||
rambase);
|
||||
|
||||
if (!zorro_request_device(z, "cirrusfb")) {
|
||||
dev_err(info->device, "Cannot reserve %pR\n", &z->resource);
|
||||
error = -EBUSY;
|
||||
goto err_release_fb;
|
||||
}
|
||||
|
||||
cinfo = info->par;
|
||||
cinfo->btype = btype;
|
||||
|
||||
assert(z);
|
||||
assert(btype != BT_NONE);
|
||||
|
||||
board_addr = zorro_resource_start(z);
|
||||
board_size = zorro_resource_len(z);
|
||||
info->screen_size = size;
|
||||
|
||||
if (!zorro_request_device(z, "cirrusfb")) {
|
||||
dev_err(info->device, "cannot reserve region 0x%lx, abort\n",
|
||||
board_addr);
|
||||
ret = -EBUSY;
|
||||
goto err_release_fb;
|
||||
info->fix.mmio_start = regbase;
|
||||
cinfo->regbase = regbase > 16 * MB_ ? ioremap(regbase, 64 * 1024)
|
||||
: (caddr_t)ZTWO_VADDR(regbase);
|
||||
if (!cinfo->regbase) {
|
||||
dev_err(info->device, "Cannot map registers\n");
|
||||
error = -EIO;
|
||||
goto err_release_dev;
|
||||
}
|
||||
|
||||
ret = -EIO;
|
||||
|
||||
if (btype == BT_PICASSO4) {
|
||||
dev_info(info->device, " REG at $%lx\n", board_addr + 0x600000);
|
||||
|
||||
/* To be precise, for the P4 this is not the */
|
||||
/* begin of the board, but the begin of RAM. */
|
||||
/* for P4, map in its address space in 2 chunks (### TEST! ) */
|
||||
/* (note the ugly hardcoded 16M number) */
|
||||
cinfo->regbase = ioremap(board_addr, 16777216);
|
||||
if (!cinfo->regbase)
|
||||
goto err_release_region;
|
||||
|
||||
dev_dbg(info->device, "Virtual address for board set to: $%p\n",
|
||||
cinfo->regbase);
|
||||
cinfo->regbase += 0x600000;
|
||||
info->fix.mmio_start = board_addr + 0x600000;
|
||||
|
||||
info->fix.smem_start = board_addr + 16777216;
|
||||
info->screen_base = ioremap(info->fix.smem_start, 16777216);
|
||||
if (!info->screen_base)
|
||||
goto err_unmap_regbase;
|
||||
} else {
|
||||
dev_info(info->device, " REG at $%lx\n",
|
||||
(unsigned long) z2->resource.start);
|
||||
|
||||
info->fix.smem_start = board_addr;
|
||||
if (board_addr > 0x01000000)
|
||||
info->screen_base = ioremap(board_addr, board_size);
|
||||
else
|
||||
info->screen_base = (caddr_t) ZTWO_VADDR(board_addr);
|
||||
if (!info->screen_base)
|
||||
goto err_release_region;
|
||||
|
||||
/* set address for REG area of board */
|
||||
cinfo->regbase = (caddr_t) ZTWO_VADDR(z2->resource.start);
|
||||
info->fix.mmio_start = z2->resource.start;
|
||||
|
||||
dev_dbg(info->device, "Virtual address for board set to: $%p\n",
|
||||
cinfo->regbase);
|
||||
info->fix.smem_start = rambase;
|
||||
info->screen_size = ramsize;
|
||||
info->screen_base = rambase > 16 * MB_ ? ioremap(rambase, ramsize)
|
||||
: (caddr_t)ZTWO_VADDR(rambase);
|
||||
if (!info->screen_base) {
|
||||
dev_err(info->device, "Cannot map video RAM\n");
|
||||
error = -EIO;
|
||||
goto err_unmap_reg;
|
||||
}
|
||||
|
||||
cinfo->unmap = cirrusfb_zorro_unmap;
|
||||
|
||||
dev_info(info->device,
|
||||
"Cirrus Logic chipset on Zorro bus, RAM (%lu MB) at $%lx\n",
|
||||
board_size / MB_, board_addr);
|
||||
|
||||
zorro_set_drvdata(z, info);
|
||||
"Cirrus Logic chipset on Zorro bus, RAM (%lu MiB) at 0x%lx\n",
|
||||
ramsize / MB_, rambase);
|
||||
|
||||
/* MCLK select etc. */
|
||||
if (cirrusfb_board_info[btype].init_sr1f)
|
||||
vga_wseq(cinfo->regbase, CL_SEQR1F,
|
||||
cirrusfb_board_info[btype].sr1f);
|
||||
|
||||
ret = cirrusfb_register(info);
|
||||
if (!ret)
|
||||
return 0;
|
||||
error = cirrusfb_register(info);
|
||||
if (error) {
|
||||
dev_err(info->device, "Failed to register device, error %d\n",
|
||||
error);
|
||||
goto err_unmap_ram;
|
||||
}
|
||||
|
||||
if (btype == BT_PICASSO4 || board_addr > 0x01000000)
|
||||
zorro_set_drvdata(z, info);
|
||||
return 0;
|
||||
|
||||
err_unmap_ram:
|
||||
if (rambase > 16 * MB_)
|
||||
iounmap(info->screen_base);
|
||||
|
||||
err_unmap_regbase:
|
||||
if (btype == BT_PICASSO4)
|
||||
iounmap(cinfo->regbase - 0x600000);
|
||||
err_release_region:
|
||||
release_region(board_addr, board_size);
|
||||
err_unmap_reg:
|
||||
if (regbase > 16 * MB_)
|
||||
iounmap(cinfo->regbase);
|
||||
err_release_dev:
|
||||
zorro_release_device(z);
|
||||
err_release_fb:
|
||||
framebuffer_release(info);
|
||||
err_out:
|
||||
return ret;
|
||||
return error;
|
||||
}
|
||||
|
||||
void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
|
||||
|
@ -2338,6 +2357,7 @@ void __devexit cirrusfb_zorro_unregister(struct zorro_dev *z)
|
|||
struct fb_info *info = zorro_get_drvdata(z);
|
||||
|
||||
cirrusfb_cleanup(info);
|
||||
zorro_set_drvdata(z, NULL);
|
||||
}
|
||||
|
||||
static struct zorro_driver cirrusfb_zorro_driver = {
|
||||
|
|
|
@ -420,7 +420,7 @@ static int __init init_control(struct fb_info_control *p)
|
|||
|
||||
/* Try to pick a video mode out of NVRAM if we have one. */
|
||||
#ifdef CONFIG_NVRAM
|
||||
if (default_cmode == CMODE_NVRAM){
|
||||
if (default_cmode == CMODE_NVRAM) {
|
||||
cmode = nvram_read_byte(NV_CMODE);
|
||||
if(cmode < CMODE_8 || cmode > CMODE_32)
|
||||
cmode = CMODE_8;
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
#
|
||||
# Display drivers configuration
|
||||
#
|
||||
|
||||
menu "Display device support"
|
||||
|
||||
config DISPLAY_SUPPORT
|
||||
tristate "Display panel/monitor support"
|
||||
---help---
|
||||
This framework adds support for low-level control of a display.
|
||||
This includes support for power.
|
||||
|
||||
Enable this to be able to choose the drivers for controlling the
|
||||
physical display panel/monitor on some platforms. This not only
|
||||
covers LCD displays for PDAs but also other types of displays
|
||||
such as CRT, TVout etc.
|
||||
|
||||
To have support for your specific display panel you will have to
|
||||
select the proper drivers which depend on this option.
|
||||
|
||||
comment "Display hardware drivers"
|
||||
depends on DISPLAY_SUPPORT
|
||||
|
||||
endmenu
|
|
@ -1,6 +0,0 @@
|
|||
# Display drivers
|
||||
|
||||
display-objs := display-sysfs.o
|
||||
|
||||
obj-$(CONFIG_DISPLAY_SUPPORT) += display.o
|
||||
|
|
@ -1,219 +0,0 @@
|
|||
/*
|
||||
* display-sysfs.c - Display output driver sysfs interface
|
||||
*
|
||||
* Copyright (C) 2007 James Simmons <jsimmons@infradead.org>
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/display.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
static ssize_t display_show_name(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct display_device *dsp = dev_get_drvdata(dev);
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", dsp->name);
|
||||
}
|
||||
|
||||
static ssize_t display_show_type(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct display_device *dsp = dev_get_drvdata(dev);
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", dsp->type);
|
||||
}
|
||||
|
||||
static ssize_t display_show_contrast(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct display_device *dsp = dev_get_drvdata(dev);
|
||||
ssize_t rc = -ENXIO;
|
||||
|
||||
mutex_lock(&dsp->lock);
|
||||
if (likely(dsp->driver) && dsp->driver->get_contrast)
|
||||
rc = sprintf(buf, "%d\n", dsp->driver->get_contrast(dsp));
|
||||
mutex_unlock(&dsp->lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t display_store_contrast(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct display_device *dsp = dev_get_drvdata(dev);
|
||||
ssize_t ret = -EINVAL, size;
|
||||
int contrast;
|
||||
char *endp;
|
||||
|
||||
contrast = simple_strtoul(buf, &endp, 0);
|
||||
size = endp - buf;
|
||||
|
||||
if (isspace(*endp))
|
||||
size++;
|
||||
|
||||
if (size != count)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&dsp->lock);
|
||||
if (likely(dsp->driver && dsp->driver->set_contrast)) {
|
||||
pr_debug("display: set contrast to %d\n", contrast);
|
||||
dsp->driver->set_contrast(dsp, contrast);
|
||||
ret = count;
|
||||
}
|
||||
mutex_unlock(&dsp->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t display_show_max_contrast(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct display_device *dsp = dev_get_drvdata(dev);
|
||||
ssize_t rc = -ENXIO;
|
||||
|
||||
mutex_lock(&dsp->lock);
|
||||
if (likely(dsp->driver))
|
||||
rc = sprintf(buf, "%d\n", dsp->driver->max_contrast);
|
||||
mutex_unlock(&dsp->lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct device_attribute display_attrs[] = {
|
||||
__ATTR(name, S_IRUGO, display_show_name, NULL),
|
||||
__ATTR(type, S_IRUGO, display_show_type, NULL),
|
||||
__ATTR(contrast, S_IRUGO | S_IWUSR, display_show_contrast, display_store_contrast),
|
||||
__ATTR(max_contrast, S_IRUGO, display_show_max_contrast, NULL),
|
||||
};
|
||||
|
||||
static int display_suspend(struct device *dev, pm_message_t state)
|
||||
{
|
||||
struct display_device *dsp = dev_get_drvdata(dev);
|
||||
|
||||
mutex_lock(&dsp->lock);
|
||||
if (likely(dsp->driver->suspend))
|
||||
dsp->driver->suspend(dsp, state);
|
||||
mutex_unlock(&dsp->lock);
|
||||
return 0;
|
||||
};
|
||||
|
||||
static int display_resume(struct device *dev)
|
||||
{
|
||||
struct display_device *dsp = dev_get_drvdata(dev);
|
||||
|
||||
mutex_lock(&dsp->lock);
|
||||
if (likely(dsp->driver->resume))
|
||||
dsp->driver->resume(dsp);
|
||||
mutex_unlock(&dsp->lock);
|
||||
return 0;
|
||||
};
|
||||
|
||||
static struct mutex allocated_dsp_lock;
|
||||
static DEFINE_IDR(allocated_dsp);
|
||||
static struct class *display_class;
|
||||
|
||||
struct display_device *display_device_register(struct display_driver *driver,
|
||||
struct device *parent, void *devdata)
|
||||
{
|
||||
struct display_device *new_dev = NULL;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (unlikely(!driver))
|
||||
return ERR_PTR(ret);
|
||||
|
||||
mutex_lock(&allocated_dsp_lock);
|
||||
ret = idr_pre_get(&allocated_dsp, GFP_KERNEL);
|
||||
mutex_unlock(&allocated_dsp_lock);
|
||||
if (!ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
new_dev = kzalloc(sizeof(struct display_device), GFP_KERNEL);
|
||||
if (likely(new_dev) && unlikely(driver->probe(new_dev, devdata))) {
|
||||
// Reserve the index for this display
|
||||
mutex_lock(&allocated_dsp_lock);
|
||||
ret = idr_get_new(&allocated_dsp, new_dev, &new_dev->idx);
|
||||
mutex_unlock(&allocated_dsp_lock);
|
||||
|
||||
if (!ret) {
|
||||
new_dev->dev = device_create(display_class, parent,
|
||||
MKDEV(0, 0), new_dev,
|
||||
"display%d", new_dev->idx);
|
||||
if (!IS_ERR(new_dev->dev)) {
|
||||
new_dev->parent = parent;
|
||||
new_dev->driver = driver;
|
||||
mutex_init(&new_dev->lock);
|
||||
return new_dev;
|
||||
}
|
||||
mutex_lock(&allocated_dsp_lock);
|
||||
idr_remove(&allocated_dsp, new_dev->idx);
|
||||
mutex_unlock(&allocated_dsp_lock);
|
||||
ret = -EINVAL;
|
||||
}
|
||||
}
|
||||
kfree(new_dev);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL(display_device_register);
|
||||
|
||||
void display_device_unregister(struct display_device *ddev)
|
||||
{
|
||||
if (!ddev)
|
||||
return;
|
||||
// Free device
|
||||
mutex_lock(&ddev->lock);
|
||||
device_unregister(ddev->dev);
|
||||
mutex_unlock(&ddev->lock);
|
||||
// Mark device index as available
|
||||
mutex_lock(&allocated_dsp_lock);
|
||||
idr_remove(&allocated_dsp, ddev->idx);
|
||||
mutex_unlock(&allocated_dsp_lock);
|
||||
kfree(ddev);
|
||||
}
|
||||
EXPORT_SYMBOL(display_device_unregister);
|
||||
|
||||
static int __init display_class_init(void)
|
||||
{
|
||||
display_class = class_create(THIS_MODULE, "display");
|
||||
if (IS_ERR(display_class)) {
|
||||
printk(KERN_ERR "Failed to create display class\n");
|
||||
display_class = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
display_class->dev_attrs = display_attrs;
|
||||
display_class->suspend = display_suspend;
|
||||
display_class->resume = display_resume;
|
||||
mutex_init(&allocated_dsp_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit display_class_exit(void)
|
||||
{
|
||||
class_destroy(display_class);
|
||||
}
|
||||
|
||||
module_init(display_class_init);
|
||||
module_exit(display_class_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Display Hardware handling");
|
||||
MODULE_AUTHOR("James Simmons <jsimmons@infradead.org>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -967,6 +967,20 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
|
|||
memcmp(&info->var, var, sizeof(struct fb_var_screeninfo))) {
|
||||
u32 activate = var->activate;
|
||||
|
||||
/* When using FOURCC mode, make sure the red, green, blue and
|
||||
* transp fields are set to 0.
|
||||
*/
|
||||
if ((info->fix.capabilities & FB_CAP_FOURCC) &&
|
||||
var->grayscale > 1) {
|
||||
if (var->red.offset || var->green.offset ||
|
||||
var->blue.offset || var->transp.offset ||
|
||||
var->red.length || var->green.length ||
|
||||
var->blue.length || var->transp.length ||
|
||||
var->red.msb_right || var->green.msb_right ||
|
||||
var->blue.msb_right || var->transp.msb_right)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!info->fbops->fb_check_var) {
|
||||
*var = info->var;
|
||||
goto done;
|
||||
|
|
|
@ -36,8 +36,7 @@
|
|||
#include <linux/fsl-diu-fb.h>
|
||||
#include "edid.h"
|
||||
|
||||
#define FSL_AOI_NUM 6 /* 5 AOIs and one dummy AOI */
|
||||
/* 1 for plane 0, 2 for plane 1&2 each */
|
||||
#define NUM_AOIS 5 /* 1 for plane 0, 2 for planes 1 & 2 each */
|
||||
|
||||
/* HW cursor parameters */
|
||||
#define MAX_CURS 32
|
||||
|
@ -49,12 +48,6 @@
|
|||
#define INT_PARERR 0x08 /* Display parameters error interrupt */
|
||||
#define INT_LS_BF_VS 0x10 /* Lines before vsync. interrupt */
|
||||
|
||||
struct diu_addr {
|
||||
void *vaddr; /* Virtual address */
|
||||
dma_addr_t paddr; /* Physical address */
|
||||
__u32 offset;
|
||||
};
|
||||
|
||||
/*
|
||||
* List of supported video modes
|
||||
*
|
||||
|
@ -330,23 +323,6 @@ static unsigned int d_cache_line_size;
|
|||
|
||||
static DEFINE_SPINLOCK(diu_lock);
|
||||
|
||||
struct fsl_diu_data {
|
||||
struct fb_info *fsl_diu_info[FSL_AOI_NUM - 1];
|
||||
/*FSL_AOI_NUM has one dummy AOI */
|
||||
struct device_attribute dev_attr;
|
||||
struct diu_ad *dummy_ad;
|
||||
void *dummy_aoi_virt;
|
||||
unsigned int irq;
|
||||
int fb_enabled;
|
||||
enum fsl_diu_monitor_port monitor_port;
|
||||
struct diu __iomem *diu_reg;
|
||||
spinlock_t reg_lock;
|
||||
struct diu_addr ad;
|
||||
struct diu_addr gamma;
|
||||
struct diu_addr pallete;
|
||||
struct diu_addr cursor;
|
||||
};
|
||||
|
||||
enum mfb_index {
|
||||
PLANE0 = 0, /* Plane 0, only one AOI that fills the screen */
|
||||
PLANE1_AOI0, /* Plane 1, first AOI */
|
||||
|
@ -370,6 +346,42 @@ struct mfb_info {
|
|||
u8 *edid_data;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct fsl_diu_data - per-DIU data structure
|
||||
* @dma_addr: DMA address of this structure
|
||||
* @fsl_diu_info: fb_info objects, one per AOI
|
||||
* @dev_attr: sysfs structure
|
||||
* @irq: IRQ
|
||||
* @monitor_port: the monitor port this DIU is connected to
|
||||
* @diu_reg: pointer to the DIU hardware registers
|
||||
* @reg_lock: spinlock for register access
|
||||
* @dummy_aoi: video buffer for the 4x4 32-bit dummy AOI
|
||||
* dummy_ad: DIU Area Descriptor for the dummy AOI
|
||||
* @ad[]: Area Descriptors for each real AOI
|
||||
* @gamma: gamma color table
|
||||
* @cursor: hardware cursor data
|
||||
*
|
||||
* This data structure must be allocated with 32-byte alignment, so that the
|
||||
* internal fields can be aligned properly.
|
||||
*/
|
||||
struct fsl_diu_data {
|
||||
dma_addr_t dma_addr;
|
||||
struct fb_info fsl_diu_info[NUM_AOIS];
|
||||
struct mfb_info mfb[NUM_AOIS];
|
||||
struct device_attribute dev_attr;
|
||||
unsigned int irq;
|
||||
enum fsl_diu_monitor_port monitor_port;
|
||||
struct diu __iomem *diu_reg;
|
||||
spinlock_t reg_lock;
|
||||
u8 dummy_aoi[4 * 4 * 4];
|
||||
struct diu_ad dummy_ad __aligned(8);
|
||||
struct diu_ad ad[NUM_AOIS] __aligned(8);
|
||||
u8 gamma[256 * 3] __aligned(32);
|
||||
u8 cursor[MAX_CURS * MAX_CURS * 2] __aligned(32);
|
||||
} __aligned(32);
|
||||
|
||||
/* Determine the DMA address of a member of the fsl_diu_data structure */
|
||||
#define DMA_ADDR(p, f) ((p)->dma_addr + offsetof(struct fsl_diu_data, f))
|
||||
|
||||
static struct mfb_info mfb_template[] = {
|
||||
{
|
||||
|
@ -449,37 +461,6 @@ static enum fsl_diu_monitor_port fsl_diu_name_to_port(const char *s)
|
|||
return diu_ops.valid_monitor_port(port);
|
||||
}
|
||||
|
||||
/**
|
||||
* fsl_diu_alloc - allocate memory for the DIU
|
||||
* @size: number of bytes to allocate
|
||||
* @param: returned physical address of memory
|
||||
*
|
||||
* This function allocates a physically-contiguous block of memory.
|
||||
*/
|
||||
static void *fsl_diu_alloc(size_t size, phys_addr_t *phys)
|
||||
{
|
||||
void *virt;
|
||||
|
||||
virt = alloc_pages_exact(size, GFP_DMA | __GFP_ZERO);
|
||||
if (virt)
|
||||
*phys = virt_to_phys(virt);
|
||||
|
||||
return virt;
|
||||
}
|
||||
|
||||
/**
|
||||
* fsl_diu_free - release DIU memory
|
||||
* @virt: pointer returned by fsl_diu_alloc()
|
||||
* @size: number of bytes allocated by fsl_diu_alloc()
|
||||
*
|
||||
* This function releases memory allocated by fsl_diu_alloc().
|
||||
*/
|
||||
static void fsl_diu_free(void *virt, size_t size)
|
||||
{
|
||||
if (virt && size)
|
||||
free_pages_exact(virt, size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Workaround for failed writing desc register of planes.
|
||||
* Needed with MPC5121 DIU rev 2.0 silicon.
|
||||
|
@ -495,8 +476,8 @@ static void fsl_diu_enable_panel(struct fb_info *info)
|
|||
{
|
||||
struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par;
|
||||
struct diu_ad *ad = mfbi->ad;
|
||||
struct fsl_diu_data *machine_data = mfbi->parent;
|
||||
struct diu __iomem *hw = machine_data->diu_reg;
|
||||
struct fsl_diu_data *data = mfbi->parent;
|
||||
struct diu __iomem *hw = data->diu_reg;
|
||||
|
||||
switch (mfbi->index) {
|
||||
case PLANE0:
|
||||
|
@ -504,7 +485,7 @@ static void fsl_diu_enable_panel(struct fb_info *info)
|
|||
wr_reg_wa(&hw->desc[0], ad->paddr);
|
||||
break;
|
||||
case PLANE1_AOI0:
|
||||
cmfbi = machine_data->fsl_diu_info[2]->par;
|
||||
cmfbi = &data->mfb[2];
|
||||
if (hw->desc[1] != ad->paddr) { /* AOI0 closed */
|
||||
if (cmfbi->count > 0) /* AOI1 open */
|
||||
ad->next_ad =
|
||||
|
@ -515,7 +496,7 @@ static void fsl_diu_enable_panel(struct fb_info *info)
|
|||
}
|
||||
break;
|
||||
case PLANE2_AOI0:
|
||||
cmfbi = machine_data->fsl_diu_info[4]->par;
|
||||
cmfbi = &data->mfb[4];
|
||||
if (hw->desc[2] != ad->paddr) { /* AOI0 closed */
|
||||
if (cmfbi->count > 0) /* AOI1 open */
|
||||
ad->next_ad =
|
||||
|
@ -526,17 +507,17 @@ static void fsl_diu_enable_panel(struct fb_info *info)
|
|||
}
|
||||
break;
|
||||
case PLANE1_AOI1:
|
||||
pmfbi = machine_data->fsl_diu_info[1]->par;
|
||||
pmfbi = &data->mfb[1];
|
||||
ad->next_ad = 0;
|
||||
if (hw->desc[1] == machine_data->dummy_ad->paddr)
|
||||
if (hw->desc[1] == data->dummy_ad.paddr)
|
||||
wr_reg_wa(&hw->desc[1], ad->paddr);
|
||||
else /* AOI0 open */
|
||||
pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
|
||||
break;
|
||||
case PLANE2_AOI1:
|
||||
pmfbi = machine_data->fsl_diu_info[3]->par;
|
||||
pmfbi = &data->mfb[3];
|
||||
ad->next_ad = 0;
|
||||
if (hw->desc[2] == machine_data->dummy_ad->paddr)
|
||||
if (hw->desc[2] == data->dummy_ad.paddr)
|
||||
wr_reg_wa(&hw->desc[2], ad->paddr);
|
||||
else /* AOI0 was open */
|
||||
pmfbi->ad->next_ad = cpu_to_le32(ad->paddr);
|
||||
|
@ -548,52 +529,52 @@ static void fsl_diu_disable_panel(struct fb_info *info)
|
|||
{
|
||||
struct mfb_info *pmfbi, *cmfbi, *mfbi = info->par;
|
||||
struct diu_ad *ad = mfbi->ad;
|
||||
struct fsl_diu_data *machine_data = mfbi->parent;
|
||||
struct diu __iomem *hw = machine_data->diu_reg;
|
||||
struct fsl_diu_data *data = mfbi->parent;
|
||||
struct diu __iomem *hw = data->diu_reg;
|
||||
|
||||
switch (mfbi->index) {
|
||||
case PLANE0:
|
||||
if (hw->desc[0] != machine_data->dummy_ad->paddr)
|
||||
wr_reg_wa(&hw->desc[0], machine_data->dummy_ad->paddr);
|
||||
if (hw->desc[0] != data->dummy_ad.paddr)
|
||||
wr_reg_wa(&hw->desc[0], data->dummy_ad.paddr);
|
||||
break;
|
||||
case PLANE1_AOI0:
|
||||
cmfbi = machine_data->fsl_diu_info[2]->par;
|
||||
cmfbi = &data->mfb[2];
|
||||
if (cmfbi->count > 0) /* AOI1 is open */
|
||||
wr_reg_wa(&hw->desc[1], cmfbi->ad->paddr);
|
||||
/* move AOI1 to the first */
|
||||
else /* AOI1 was closed */
|
||||
wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr);
|
||||
wr_reg_wa(&hw->desc[1], data->dummy_ad.paddr);
|
||||
/* close AOI 0 */
|
||||
break;
|
||||
case PLANE2_AOI0:
|
||||
cmfbi = machine_data->fsl_diu_info[4]->par;
|
||||
cmfbi = &data->mfb[4];
|
||||
if (cmfbi->count > 0) /* AOI1 is open */
|
||||
wr_reg_wa(&hw->desc[2], cmfbi->ad->paddr);
|
||||
/* move AOI1 to the first */
|
||||
else /* AOI1 was closed */
|
||||
wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr);
|
||||
wr_reg_wa(&hw->desc[2], data->dummy_ad.paddr);
|
||||
/* close AOI 0 */
|
||||
break;
|
||||
case PLANE1_AOI1:
|
||||
pmfbi = machine_data->fsl_diu_info[1]->par;
|
||||
pmfbi = &data->mfb[1];
|
||||
if (hw->desc[1] != ad->paddr) {
|
||||
/* AOI1 is not the first in the chain */
|
||||
if (pmfbi->count > 0)
|
||||
/* AOI0 is open, must be the first */
|
||||
pmfbi->ad->next_ad = 0;
|
||||
} else /* AOI1 is the first in the chain */
|
||||
wr_reg_wa(&hw->desc[1], machine_data->dummy_ad->paddr);
|
||||
wr_reg_wa(&hw->desc[1], data->dummy_ad.paddr);
|
||||
/* close AOI 1 */
|
||||
break;
|
||||
case PLANE2_AOI1:
|
||||
pmfbi = machine_data->fsl_diu_info[3]->par;
|
||||
pmfbi = &data->mfb[3];
|
||||
if (hw->desc[2] != ad->paddr) {
|
||||
/* AOI1 is not the first in the chain */
|
||||
if (pmfbi->count > 0)
|
||||
/* AOI0 is open, must be the first */
|
||||
pmfbi->ad->next_ad = 0;
|
||||
} else /* AOI1 is the first in the chain */
|
||||
wr_reg_wa(&hw->desc[2], machine_data->dummy_ad->paddr);
|
||||
wr_reg_wa(&hw->desc[2], data->dummy_ad.paddr);
|
||||
/* close AOI 1 */
|
||||
break;
|
||||
}
|
||||
|
@ -602,39 +583,33 @@ static void fsl_diu_disable_panel(struct fb_info *info)
|
|||
static void enable_lcdc(struct fb_info *info)
|
||||
{
|
||||
struct mfb_info *mfbi = info->par;
|
||||
struct fsl_diu_data *machine_data = mfbi->parent;
|
||||
struct diu __iomem *hw = machine_data->diu_reg;
|
||||
struct fsl_diu_data *data = mfbi->parent;
|
||||
struct diu __iomem *hw = data->diu_reg;
|
||||
|
||||
if (!machine_data->fb_enabled) {
|
||||
out_be32(&hw->diu_mode, MFB_MODE1);
|
||||
machine_data->fb_enabled++;
|
||||
}
|
||||
out_be32(&hw->diu_mode, MFB_MODE1);
|
||||
}
|
||||
|
||||
static void disable_lcdc(struct fb_info *info)
|
||||
{
|
||||
struct mfb_info *mfbi = info->par;
|
||||
struct fsl_diu_data *machine_data = mfbi->parent;
|
||||
struct diu __iomem *hw = machine_data->diu_reg;
|
||||
struct fsl_diu_data *data = mfbi->parent;
|
||||
struct diu __iomem *hw = data->diu_reg;
|
||||
|
||||
if (machine_data->fb_enabled) {
|
||||
out_be32(&hw->diu_mode, 0);
|
||||
machine_data->fb_enabled = 0;
|
||||
}
|
||||
out_be32(&hw->diu_mode, 0);
|
||||
}
|
||||
|
||||
static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
|
||||
struct fb_info *info)
|
||||
{
|
||||
struct mfb_info *lower_aoi_mfbi, *upper_aoi_mfbi, *mfbi = info->par;
|
||||
struct fsl_diu_data *machine_data = mfbi->parent;
|
||||
struct fsl_diu_data *data = mfbi->parent;
|
||||
int available_height, upper_aoi_bottom;
|
||||
enum mfb_index index = mfbi->index;
|
||||
int lower_aoi_is_open, upper_aoi_is_open;
|
||||
__u32 base_plane_width, base_plane_height, upper_aoi_height;
|
||||
|
||||
base_plane_width = machine_data->fsl_diu_info[0]->var.xres;
|
||||
base_plane_height = machine_data->fsl_diu_info[0]->var.yres;
|
||||
base_plane_width = data->fsl_diu_info[0].var.xres;
|
||||
base_plane_height = data->fsl_diu_info[0].var.yres;
|
||||
|
||||
if (mfbi->x_aoi_d < 0)
|
||||
mfbi->x_aoi_d = 0;
|
||||
|
@ -649,7 +624,7 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
|
|||
break;
|
||||
case PLANE1_AOI0:
|
||||
case PLANE2_AOI0:
|
||||
lower_aoi_mfbi = machine_data->fsl_diu_info[index+1]->par;
|
||||
lower_aoi_mfbi = data->fsl_diu_info[index+1].par;
|
||||
lower_aoi_is_open = lower_aoi_mfbi->count > 0 ? 1 : 0;
|
||||
if (var->xres > base_plane_width)
|
||||
var->xres = base_plane_width;
|
||||
|
@ -667,9 +642,8 @@ static void adjust_aoi_size_position(struct fb_var_screeninfo *var,
|
|||
break;
|
||||
case PLANE1_AOI1:
|
||||
case PLANE2_AOI1:
|
||||
upper_aoi_mfbi = machine_data->fsl_diu_info[index-1]->par;
|
||||
upper_aoi_height =
|
||||
machine_data->fsl_diu_info[index-1]->var.yres;
|
||||
upper_aoi_mfbi = data->fsl_diu_info[index-1].par;
|
||||
upper_aoi_height = data->fsl_diu_info[index-1].var.yres;
|
||||
upper_aoi_bottom = upper_aoi_mfbi->y_aoi_d + upper_aoi_height;
|
||||
upper_aoi_is_open = upper_aoi_mfbi->count > 0 ? 1 : 0;
|
||||
if (var->xres > base_plane_width)
|
||||
|
@ -809,33 +783,33 @@ static void update_lcdc(struct fb_info *info)
|
|||
{
|
||||
struct fb_var_screeninfo *var = &info->var;
|
||||
struct mfb_info *mfbi = info->par;
|
||||
struct fsl_diu_data *machine_data = mfbi->parent;
|
||||
struct fsl_diu_data *data = mfbi->parent;
|
||||
struct diu __iomem *hw;
|
||||
int i, j;
|
||||
char __iomem *cursor_base, *gamma_table_base;
|
||||
u8 *gamma_table_base;
|
||||
|
||||
u32 temp;
|
||||
|
||||
hw = machine_data->diu_reg;
|
||||
hw = data->diu_reg;
|
||||
|
||||
diu_ops.set_monitor_port(data->monitor_port);
|
||||
gamma_table_base = data->gamma;
|
||||
|
||||
diu_ops.set_monitor_port(machine_data->monitor_port);
|
||||
gamma_table_base = machine_data->gamma.vaddr;
|
||||
cursor_base = machine_data->cursor.vaddr;
|
||||
/* Prep for DIU init - gamma table, cursor table */
|
||||
|
||||
for (i = 0; i <= 2; i++)
|
||||
for (j = 0; j <= 255; j++)
|
||||
*gamma_table_base++ = j;
|
||||
|
||||
diu_ops.set_gamma_table(machine_data->monitor_port,
|
||||
machine_data->gamma.vaddr);
|
||||
if (diu_ops.set_gamma_table)
|
||||
diu_ops.set_gamma_table(data->monitor_port, data->gamma);
|
||||
|
||||
disable_lcdc(info);
|
||||
|
||||
/* Program DIU registers */
|
||||
|
||||
out_be32(&hw->gamma, machine_data->gamma.paddr);
|
||||
out_be32(&hw->cursor, machine_data->cursor.paddr);
|
||||
out_be32(&hw->gamma, DMA_ADDR(data, gamma));
|
||||
out_be32(&hw->cursor, DMA_ADDR(data, cursor));
|
||||
|
||||
out_be32(&hw->bgnd, 0x007F7F7F); /* BGND */
|
||||
out_be32(&hw->bgnd_wb, 0); /* BGND_WB */
|
||||
|
@ -870,16 +844,17 @@ static void update_lcdc(struct fb_info *info)
|
|||
|
||||
static int map_video_memory(struct fb_info *info)
|
||||
{
|
||||
phys_addr_t phys;
|
||||
u32 smem_len = info->fix.line_length * info->var.yres_virtual;
|
||||
void *p;
|
||||
|
||||
info->screen_base = fsl_diu_alloc(smem_len, &phys);
|
||||
if (info->screen_base == NULL) {
|
||||
p = alloc_pages_exact(smem_len, GFP_DMA | __GFP_ZERO);
|
||||
if (!p) {
|
||||
dev_err(info->dev, "unable to allocate fb memory\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
mutex_lock(&info->mm_lock);
|
||||
info->fix.smem_start = (unsigned long) phys;
|
||||
info->screen_base = p;
|
||||
info->fix.smem_start = virt_to_phys(info->screen_base);
|
||||
info->fix.smem_len = smem_len;
|
||||
mutex_unlock(&info->mm_lock);
|
||||
info->screen_size = info->fix.smem_len;
|
||||
|
@ -889,12 +864,17 @@ static int map_video_memory(struct fb_info *info)
|
|||
|
||||
static void unmap_video_memory(struct fb_info *info)
|
||||
{
|
||||
fsl_diu_free(info->screen_base, info->fix.smem_len);
|
||||
void *p = info->screen_base;
|
||||
size_t l = info->fix.smem_len;
|
||||
|
||||
mutex_lock(&info->mm_lock);
|
||||
info->screen_base = NULL;
|
||||
info->fix.smem_start = 0;
|
||||
info->fix.smem_len = 0;
|
||||
mutex_unlock(&info->mm_lock);
|
||||
|
||||
if (p)
|
||||
free_pages_exact(p, l);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -913,6 +893,59 @@ static int fsl_diu_set_aoi(struct fb_info *info)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* fsl_diu_get_pixel_format: return the pixel format for a given color depth
|
||||
*
|
||||
* The pixel format is a 32-bit value that determine which bits in each
|
||||
* pixel are to be used for each color. This is the default function used
|
||||
* if the platform does not define its own version.
|
||||
*/
|
||||
static u32 fsl_diu_get_pixel_format(unsigned int bits_per_pixel)
|
||||
{
|
||||
#define PF_BYTE_F 0x10000000
|
||||
#define PF_ALPHA_C_MASK 0x0E000000
|
||||
#define PF_ALPHA_C_SHIFT 25
|
||||
#define PF_BLUE_C_MASK 0x01800000
|
||||
#define PF_BLUE_C_SHIFT 23
|
||||
#define PF_GREEN_C_MASK 0x00600000
|
||||
#define PF_GREEN_C_SHIFT 21
|
||||
#define PF_RED_C_MASK 0x00180000
|
||||
#define PF_RED_C_SHIFT 19
|
||||
#define PF_PALETTE 0x00040000
|
||||
#define PF_PIXEL_S_MASK 0x00030000
|
||||
#define PF_PIXEL_S_SHIFT 16
|
||||
#define PF_COMP_3_MASK 0x0000F000
|
||||
#define PF_COMP_3_SHIFT 12
|
||||
#define PF_COMP_2_MASK 0x00000F00
|
||||
#define PF_COMP_2_SHIFT 8
|
||||
#define PF_COMP_1_MASK 0x000000F0
|
||||
#define PF_COMP_1_SHIFT 4
|
||||
#define PF_COMP_0_MASK 0x0000000F
|
||||
#define PF_COMP_0_SHIFT 0
|
||||
|
||||
#define MAKE_PF(alpha, red, blue, green, size, c0, c1, c2, c3) \
|
||||
cpu_to_le32(PF_BYTE_F | (alpha << PF_ALPHA_C_SHIFT) | \
|
||||
(blue << PF_BLUE_C_SHIFT) | (green << PF_GREEN_C_SHIFT) | \
|
||||
(red << PF_RED_C_SHIFT) | (c3 << PF_COMP_3_SHIFT) | \
|
||||
(c2 << PF_COMP_2_SHIFT) | (c1 << PF_COMP_1_SHIFT) | \
|
||||
(c0 << PF_COMP_0_SHIFT) | (size << PF_PIXEL_S_SHIFT))
|
||||
|
||||
switch (bits_per_pixel) {
|
||||
case 32:
|
||||
/* 0x88883316 */
|
||||
return MAKE_PF(3, 2, 0, 1, 3, 8, 8, 8, 8);
|
||||
case 24:
|
||||
/* 0x88082219 */
|
||||
return MAKE_PF(4, 0, 1, 2, 2, 0, 8, 8, 8);
|
||||
case 16:
|
||||
/* 0x65053118 */
|
||||
return MAKE_PF(4, 2, 1, 0, 1, 5, 6, 5, 0);
|
||||
default:
|
||||
pr_err("fsl-diu: unsupported color depth %u\n", bits_per_pixel);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Using the fb_var_screeninfo in fb_info we set the resolution of this
|
||||
* particular framebuffer. This function alters the fb_fix_screeninfo stored
|
||||
|
@ -926,11 +959,11 @@ static int fsl_diu_set_par(struct fb_info *info)
|
|||
unsigned long len;
|
||||
struct fb_var_screeninfo *var = &info->var;
|
||||
struct mfb_info *mfbi = info->par;
|
||||
struct fsl_diu_data *machine_data = mfbi->parent;
|
||||
struct fsl_diu_data *data = mfbi->parent;
|
||||
struct diu_ad *ad = mfbi->ad;
|
||||
struct diu __iomem *hw;
|
||||
|
||||
hw = machine_data->diu_reg;
|
||||
hw = data->diu_reg;
|
||||
|
||||
set_fix(info);
|
||||
mfbi->cursor_reset = 1;
|
||||
|
@ -948,8 +981,12 @@ static int fsl_diu_set_par(struct fb_info *info)
|
|||
}
|
||||
}
|
||||
|
||||
ad->pix_fmt = diu_ops.get_pixel_format(machine_data->monitor_port,
|
||||
var->bits_per_pixel);
|
||||
if (diu_ops.get_pixel_format)
|
||||
ad->pix_fmt = diu_ops.get_pixel_format(data->monitor_port,
|
||||
var->bits_per_pixel);
|
||||
else
|
||||
ad->pix_fmt = fsl_diu_get_pixel_format(var->bits_per_pixel);
|
||||
|
||||
ad->addr = cpu_to_le32(info->fix.smem_start);
|
||||
ad->src_size_g_alpha = cpu_to_le32((var->yres_virtual << 12) |
|
||||
var->xres_virtual) | mfbi->g_alpha;
|
||||
|
@ -1208,21 +1245,6 @@ static struct fb_ops fsl_diu_ops = {
|
|||
.fb_release = fsl_diu_release,
|
||||
};
|
||||
|
||||
static int init_fbinfo(struct fb_info *info)
|
||||
{
|
||||
struct mfb_info *mfbi = info->par;
|
||||
|
||||
info->device = NULL;
|
||||
info->var.activate = FB_ACTIVATE_NOW;
|
||||
info->fbops = &fsl_diu_ops;
|
||||
info->flags = FBINFO_FLAG_DEFAULT;
|
||||
info->pseudo_palette = &mfbi->pseudo_palette;
|
||||
|
||||
/* Allocate colormap */
|
||||
fb_alloc_cmap(&info->cmap, 16, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit install_fb(struct fb_info *info)
|
||||
{
|
||||
int rc;
|
||||
|
@ -1232,8 +1254,15 @@ static int __devinit install_fb(struct fb_info *info)
|
|||
unsigned int dbsize = ARRAY_SIZE(fsl_diu_mode_db);
|
||||
int has_default_mode = 1;
|
||||
|
||||
if (init_fbinfo(info))
|
||||
return -EINVAL;
|
||||
info->var.activate = FB_ACTIVATE_NOW;
|
||||
info->fbops = &fsl_diu_ops;
|
||||
info->flags = FBINFO_DEFAULT | FBINFO_VIRTFB | FBINFO_PARTIAL_PAN_OK |
|
||||
FBINFO_READS_FAST;
|
||||
info->pseudo_palette = mfbi->pseudo_palette;
|
||||
|
||||
rc = fb_alloc_cmap(&info->cmap, 16, 0);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (mfbi->index == PLANE0) {
|
||||
if (mfbi->edid_data) {
|
||||
|
@ -1359,16 +1388,16 @@ static irqreturn_t fsl_diu_isr(int irq, void *dev_id)
|
|||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
static int request_irq_local(struct fsl_diu_data *machine_data)
|
||||
static int request_irq_local(struct fsl_diu_data *data)
|
||||
{
|
||||
struct diu __iomem *hw = machine_data->diu_reg;
|
||||
struct diu __iomem *hw = data->diu_reg;
|
||||
u32 ints;
|
||||
int ret;
|
||||
|
||||
/* Read to clear the status */
|
||||
in_be32(&hw->int_status);
|
||||
|
||||
ret = request_irq(machine_data->irq, fsl_diu_isr, 0, "fsl-diu-fb", hw);
|
||||
ret = request_irq(data->irq, fsl_diu_isr, 0, "fsl-diu-fb", hw);
|
||||
if (!ret) {
|
||||
ints = INT_PARERR | INT_LS_BF_VS;
|
||||
#if !defined(CONFIG_NOT_COHERENT_CACHE)
|
||||
|
@ -1383,14 +1412,14 @@ static int request_irq_local(struct fsl_diu_data *machine_data)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void free_irq_local(struct fsl_diu_data *machine_data)
|
||||
static void free_irq_local(struct fsl_diu_data *data)
|
||||
{
|
||||
struct diu __iomem *hw = machine_data->diu_reg;
|
||||
struct diu __iomem *hw = data->diu_reg;
|
||||
|
||||
/* Disable all LCDC interrupt */
|
||||
out_be32(&hw->int_mask, 0x1f);
|
||||
|
||||
free_irq(machine_data->irq, NULL);
|
||||
free_irq(data->irq, NULL);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
@ -1400,20 +1429,20 @@ static void free_irq_local(struct fsl_diu_data *machine_data)
|
|||
*/
|
||||
static int fsl_diu_suspend(struct platform_device *ofdev, pm_message_t state)
|
||||
{
|
||||
struct fsl_diu_data *machine_data;
|
||||
struct fsl_diu_data *data;
|
||||
|
||||
machine_data = dev_get_drvdata(&ofdev->dev);
|
||||
disable_lcdc(machine_data->fsl_diu_info[0]);
|
||||
data = dev_get_drvdata(&ofdev->dev);
|
||||
disable_lcdc(data->fsl_diu_info[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fsl_diu_resume(struct platform_device *ofdev)
|
||||
{
|
||||
struct fsl_diu_data *machine_data;
|
||||
struct fsl_diu_data *data;
|
||||
|
||||
machine_data = dev_get_drvdata(&ofdev->dev);
|
||||
enable_lcdc(machine_data->fsl_diu_info[0]);
|
||||
data = dev_get_drvdata(&ofdev->dev);
|
||||
enable_lcdc(data->fsl_diu_info[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1423,56 +1452,24 @@ static int fsl_diu_resume(struct platform_device *ofdev)
|
|||
#define fsl_diu_resume NULL
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
/* Align to 64-bit(8-byte), 32-byte, etc. */
|
||||
static int allocate_buf(struct device *dev, struct diu_addr *buf, u32 size,
|
||||
u32 bytes_align)
|
||||
{
|
||||
u32 offset;
|
||||
dma_addr_t mask;
|
||||
|
||||
buf->vaddr =
|
||||
dma_alloc_coherent(dev, size + bytes_align, &buf->paddr,
|
||||
GFP_DMA | __GFP_ZERO);
|
||||
if (!buf->vaddr)
|
||||
return -ENOMEM;
|
||||
|
||||
mask = bytes_align - 1;
|
||||
offset = buf->paddr & mask;
|
||||
if (offset) {
|
||||
buf->offset = bytes_align - offset;
|
||||
buf->paddr = buf->paddr + offset;
|
||||
} else
|
||||
buf->offset = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void free_buf(struct device *dev, struct diu_addr *buf, u32 size,
|
||||
u32 bytes_align)
|
||||
{
|
||||
dma_free_coherent(dev, size + bytes_align, buf->vaddr,
|
||||
buf->paddr - buf->offset);
|
||||
}
|
||||
|
||||
static ssize_t store_monitor(struct device *device,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
enum fsl_diu_monitor_port old_monitor_port;
|
||||
struct fsl_diu_data *machine_data =
|
||||
struct fsl_diu_data *data =
|
||||
container_of(attr, struct fsl_diu_data, dev_attr);
|
||||
|
||||
old_monitor_port = machine_data->monitor_port;
|
||||
machine_data->monitor_port = fsl_diu_name_to_port(buf);
|
||||
old_monitor_port = data->monitor_port;
|
||||
data->monitor_port = fsl_diu_name_to_port(buf);
|
||||
|
||||
if (old_monitor_port != machine_data->monitor_port) {
|
||||
if (old_monitor_port != data->monitor_port) {
|
||||
/* All AOIs need adjust pixel format
|
||||
* fsl_diu_set_par only change the pixsel format here
|
||||
* unlikely to fail. */
|
||||
fsl_diu_set_par(machine_data->fsl_diu_info[0]);
|
||||
fsl_diu_set_par(machine_data->fsl_diu_info[1]);
|
||||
fsl_diu_set_par(machine_data->fsl_diu_info[2]);
|
||||
fsl_diu_set_par(machine_data->fsl_diu_info[3]);
|
||||
fsl_diu_set_par(machine_data->fsl_diu_info[4]);
|
||||
unsigned int i;
|
||||
|
||||
for (i=0; i < NUM_AOIS; i++)
|
||||
fsl_diu_set_par(&data->fsl_diu_info[i]);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
@ -1480,10 +1477,10 @@ static ssize_t store_monitor(struct device *device,
|
|||
static ssize_t show_monitor(struct device *device,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct fsl_diu_data *machine_data =
|
||||
struct fsl_diu_data *data =
|
||||
container_of(attr, struct fsl_diu_data, dev_attr);
|
||||
|
||||
switch (machine_data->monitor_port) {
|
||||
switch (data->monitor_port) {
|
||||
case FSL_DIU_PORT_DVI:
|
||||
return sprintf(buf, "DVI\n");
|
||||
case FSL_DIU_PORT_LVDS:
|
||||
|
@ -1499,28 +1496,52 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
|
|||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct mfb_info *mfbi;
|
||||
phys_addr_t dummy_ad_addr = 0;
|
||||
int ret, i, error = 0;
|
||||
struct fsl_diu_data *machine_data;
|
||||
struct fsl_diu_data *data;
|
||||
int diu_mode;
|
||||
dma_addr_t dma_addr; /* DMA addr of fsl_diu_data struct */
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
machine_data = kzalloc(sizeof(struct fsl_diu_data), GFP_KERNEL);
|
||||
if (!machine_data)
|
||||
data = dma_alloc_coherent(&pdev->dev, sizeof(struct fsl_diu_data),
|
||||
&dma_addr, GFP_DMA | __GFP_ZERO);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
data->dma_addr = dma_addr;
|
||||
|
||||
spin_lock_init(&machine_data->reg_lock);
|
||||
/*
|
||||
* dma_alloc_coherent() uses a page allocator, so the address is
|
||||
* always page-aligned. We need the memory to be 32-byte aligned,
|
||||
* so that's good. However, if one day the allocator changes, we
|
||||
* need to catch that. It's not worth the effort to handle unaligned
|
||||
* alloctions now because it's highly unlikely to ever be a problem.
|
||||
*/
|
||||
if ((unsigned long)data & 31) {
|
||||
dev_err(&pdev->dev, "misaligned allocation");
|
||||
ret = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) {
|
||||
machine_data->fsl_diu_info[i] =
|
||||
framebuffer_alloc(sizeof(struct mfb_info), &pdev->dev);
|
||||
if (!machine_data->fsl_diu_info[i]) {
|
||||
dev_err(&pdev->dev, "cannot allocate memory\n");
|
||||
ret = -ENOMEM;
|
||||
goto error2;
|
||||
}
|
||||
mfbi = machine_data->fsl_diu_info[i]->par;
|
||||
spin_lock_init(&data->reg_lock);
|
||||
|
||||
for (i = 0; i < NUM_AOIS; i++) {
|
||||
struct fb_info *info = &data->fsl_diu_info[i];
|
||||
|
||||
info->device = &pdev->dev;
|
||||
info->par = &data->mfb[i];
|
||||
|
||||
/*
|
||||
* We store the physical address of the AD in the reserved
|
||||
* 'paddr' field of the AD itself.
|
||||
*/
|
||||
data->ad[i].paddr = DMA_ADDR(data, ad[i]);
|
||||
|
||||
info->fix.smem_start = 0;
|
||||
|
||||
/* Initialize the AOI data structure */
|
||||
mfbi = info->par;
|
||||
memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info));
|
||||
mfbi->parent = machine_data;
|
||||
mfbi->parent = data;
|
||||
mfbi->ad = &data->ad[i];
|
||||
|
||||
if (mfbi->index == PLANE0) {
|
||||
const u8 *prop;
|
||||
|
@ -1534,158 +1555,102 @@ static int __devinit fsl_diu_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
machine_data->diu_reg = of_iomap(np, 0);
|
||||
if (!machine_data->diu_reg) {
|
||||
data->diu_reg = of_iomap(np, 0);
|
||||
if (!data->diu_reg) {
|
||||
dev_err(&pdev->dev, "cannot map DIU registers\n");
|
||||
ret = -EFAULT;
|
||||
goto error2;
|
||||
goto error;
|
||||
}
|
||||
|
||||
diu_mode = in_be32(&machine_data->diu_reg->diu_mode);
|
||||
diu_mode = in_be32(&data->diu_reg->diu_mode);
|
||||
if (diu_mode == MFB_MODE0)
|
||||
out_be32(&machine_data->diu_reg->diu_mode, 0); /* disable DIU */
|
||||
out_be32(&data->diu_reg->diu_mode, 0); /* disable DIU */
|
||||
|
||||
/* Get the IRQ of the DIU */
|
||||
machine_data->irq = irq_of_parse_and_map(np, 0);
|
||||
data->irq = irq_of_parse_and_map(np, 0);
|
||||
|
||||
if (!machine_data->irq) {
|
||||
if (!data->irq) {
|
||||
dev_err(&pdev->dev, "could not get DIU IRQ\n");
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
machine_data->monitor_port = monitor_port;
|
||||
data->monitor_port = monitor_port;
|
||||
|
||||
/* Area descriptor memory pool aligns to 64-bit boundary */
|
||||
if (allocate_buf(&pdev->dev, &machine_data->ad,
|
||||
sizeof(struct diu_ad) * FSL_AOI_NUM, 8))
|
||||
return -ENOMEM;
|
||||
|
||||
/* Get memory for Gamma Table - 32-byte aligned memory */
|
||||
if (allocate_buf(&pdev->dev, &machine_data->gamma, 768, 32)) {
|
||||
ret = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* For performance, cursor bitmap buffer aligns to 32-byte boundary */
|
||||
if (allocate_buf(&pdev->dev, &machine_data->cursor,
|
||||
MAX_CURS * MAX_CURS * 2, 32)) {
|
||||
ret = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
i = ARRAY_SIZE(machine_data->fsl_diu_info);
|
||||
machine_data->dummy_ad = (struct diu_ad *)((u32)machine_data->ad.vaddr +
|
||||
machine_data->ad.offset) + i;
|
||||
machine_data->dummy_ad->paddr = machine_data->ad.paddr +
|
||||
i * sizeof(struct diu_ad);
|
||||
machine_data->dummy_aoi_virt = fsl_diu_alloc(64, &dummy_ad_addr);
|
||||
if (!machine_data->dummy_aoi_virt) {
|
||||
ret = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
machine_data->dummy_ad->addr = cpu_to_le32(dummy_ad_addr);
|
||||
machine_data->dummy_ad->pix_fmt = 0x88882317;
|
||||
machine_data->dummy_ad->src_size_g_alpha = cpu_to_le32((4 << 12) | 4);
|
||||
machine_data->dummy_ad->aoi_size = cpu_to_le32((4 << 16) | 2);
|
||||
machine_data->dummy_ad->offset_xyi = 0;
|
||||
machine_data->dummy_ad->offset_xyd = 0;
|
||||
machine_data->dummy_ad->next_ad = 0;
|
||||
/* Initialize the dummy Area Descriptor */
|
||||
data->dummy_ad.addr = cpu_to_le32(DMA_ADDR(data, dummy_aoi));
|
||||
data->dummy_ad.pix_fmt = 0x88882317;
|
||||
data->dummy_ad.src_size_g_alpha = cpu_to_le32((4 << 12) | 4);
|
||||
data->dummy_ad.aoi_size = cpu_to_le32((4 << 16) | 2);
|
||||
data->dummy_ad.offset_xyi = 0;
|
||||
data->dummy_ad.offset_xyd = 0;
|
||||
data->dummy_ad.next_ad = 0;
|
||||
data->dummy_ad.paddr = DMA_ADDR(data, dummy_ad);
|
||||
|
||||
/*
|
||||
* Let DIU display splash screen if it was pre-initialized
|
||||
* by the bootloader, set dummy area descriptor otherwise.
|
||||
*/
|
||||
if (diu_mode == MFB_MODE0)
|
||||
out_be32(&machine_data->diu_reg->desc[0],
|
||||
machine_data->dummy_ad->paddr);
|
||||
out_be32(&data->diu_reg->desc[0], data->dummy_ad.paddr);
|
||||
|
||||
out_be32(&machine_data->diu_reg->desc[1], machine_data->dummy_ad->paddr);
|
||||
out_be32(&machine_data->diu_reg->desc[2], machine_data->dummy_ad->paddr);
|
||||
out_be32(&data->diu_reg->desc[1], data->dummy_ad.paddr);
|
||||
out_be32(&data->diu_reg->desc[2], data->dummy_ad.paddr);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++) {
|
||||
machine_data->fsl_diu_info[i]->fix.smem_start = 0;
|
||||
mfbi = machine_data->fsl_diu_info[i]->par;
|
||||
mfbi->ad = (struct diu_ad *)((u32)machine_data->ad.vaddr
|
||||
+ machine_data->ad.offset) + i;
|
||||
mfbi->ad->paddr =
|
||||
machine_data->ad.paddr + i * sizeof(struct diu_ad);
|
||||
ret = install_fb(machine_data->fsl_diu_info[i]);
|
||||
for (i = 0; i < NUM_AOIS; i++) {
|
||||
ret = install_fb(&data->fsl_diu_info[i]);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "could not register fb %d\n", i);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (request_irq_local(machine_data)) {
|
||||
if (request_irq_local(data)) {
|
||||
dev_err(&pdev->dev, "could not claim irq\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
sysfs_attr_init(&machine_data->dev_attr.attr);
|
||||
machine_data->dev_attr.attr.name = "monitor";
|
||||
machine_data->dev_attr.attr.mode = S_IRUGO|S_IWUSR;
|
||||
machine_data->dev_attr.show = show_monitor;
|
||||
machine_data->dev_attr.store = store_monitor;
|
||||
error = device_create_file(machine_data->fsl_diu_info[0]->dev,
|
||||
&machine_data->dev_attr);
|
||||
if (error) {
|
||||
sysfs_attr_init(&data->dev_attr.attr);
|
||||
data->dev_attr.attr.name = "monitor";
|
||||
data->dev_attr.attr.mode = S_IRUGO|S_IWUSR;
|
||||
data->dev_attr.show = show_monitor;
|
||||
data->dev_attr.store = store_monitor;
|
||||
ret = device_create_file(&pdev->dev, &data->dev_attr);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "could not create sysfs file %s\n",
|
||||
machine_data->dev_attr.attr.name);
|
||||
data->dev_attr.attr.name);
|
||||
}
|
||||
|
||||
dev_set_drvdata(&pdev->dev, machine_data);
|
||||
dev_set_drvdata(&pdev->dev, data);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++)
|
||||
uninstall_fb(machine_data->fsl_diu_info[i]);
|
||||
for (i = 0; i < NUM_AOIS; i++)
|
||||
uninstall_fb(&data->fsl_diu_info[i]);
|
||||
|
||||
if (machine_data->ad.vaddr)
|
||||
free_buf(&pdev->dev, &machine_data->ad,
|
||||
sizeof(struct diu_ad) * FSL_AOI_NUM, 8);
|
||||
if (machine_data->gamma.vaddr)
|
||||
free_buf(&pdev->dev, &machine_data->gamma, 768, 32);
|
||||
if (machine_data->cursor.vaddr)
|
||||
free_buf(&pdev->dev, &machine_data->cursor,
|
||||
MAX_CURS * MAX_CURS * 2, 32);
|
||||
if (machine_data->dummy_aoi_virt)
|
||||
fsl_diu_free(machine_data->dummy_aoi_virt, 64);
|
||||
iounmap(machine_data->diu_reg);
|
||||
iounmap(data->diu_reg);
|
||||
|
||||
error2:
|
||||
for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++)
|
||||
if (machine_data->fsl_diu_info[i])
|
||||
framebuffer_release(machine_data->fsl_diu_info[i]);
|
||||
kfree(machine_data);
|
||||
dma_free_coherent(&pdev->dev, sizeof(struct fsl_diu_data), data,
|
||||
data->dma_addr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fsl_diu_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct fsl_diu_data *machine_data;
|
||||
struct fsl_diu_data *data;
|
||||
int i;
|
||||
|
||||
machine_data = dev_get_drvdata(&pdev->dev);
|
||||
disable_lcdc(machine_data->fsl_diu_info[0]);
|
||||
free_irq_local(machine_data);
|
||||
for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++)
|
||||
uninstall_fb(machine_data->fsl_diu_info[i]);
|
||||
if (machine_data->ad.vaddr)
|
||||
free_buf(&pdev->dev, &machine_data->ad,
|
||||
sizeof(struct diu_ad) * FSL_AOI_NUM, 8);
|
||||
if (machine_data->gamma.vaddr)
|
||||
free_buf(&pdev->dev, &machine_data->gamma, 768, 32);
|
||||
if (machine_data->cursor.vaddr)
|
||||
free_buf(&pdev->dev, &machine_data->cursor,
|
||||
MAX_CURS * MAX_CURS * 2, 32);
|
||||
if (machine_data->dummy_aoi_virt)
|
||||
fsl_diu_free(machine_data->dummy_aoi_virt, 64);
|
||||
iounmap(machine_data->diu_reg);
|
||||
for (i = 0; i < ARRAY_SIZE(machine_data->fsl_diu_info); i++)
|
||||
if (machine_data->fsl_diu_info[i])
|
||||
framebuffer_release(machine_data->fsl_diu_info[i]);
|
||||
kfree(machine_data);
|
||||
data = dev_get_drvdata(&pdev->dev);
|
||||
disable_lcdc(&data->fsl_diu_info[0]);
|
||||
free_irq_local(data);
|
||||
|
||||
for (i = 0; i < NUM_AOIS; i++)
|
||||
uninstall_fb(&data->fsl_diu_info[i]);
|
||||
|
||||
iounmap(data->diu_reg);
|
||||
|
||||
dma_free_coherent(&pdev->dev, sizeof(struct fsl_diu_data), data,
|
||||
data->dma_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ static const struct fb_videomode grvga_modedb[] = {
|
|||
}
|
||||
};
|
||||
|
||||
static struct fb_fix_screeninfo grvga_fix __initdata = {
|
||||
static struct fb_fix_screeninfo grvga_fix __devinitdata = {
|
||||
.id = "AG SVGACTRL",
|
||||
.type = FB_TYPE_PACKED_PIXELS,
|
||||
.visual = FB_VISUAL_PSEUDOCOLOR,
|
||||
|
@ -267,7 +267,7 @@ static struct fb_ops grvga_ops = {
|
|||
.fb_imageblit = cfb_imageblit
|
||||
};
|
||||
|
||||
static int __init grvga_parse_custom(char *options,
|
||||
static int __devinit grvga_parse_custom(char *options,
|
||||
struct fb_var_screeninfo *screendata)
|
||||
{
|
||||
char *this_opt;
|
||||
|
|
|
@ -135,8 +135,8 @@ static struct pci_driver i810fb_driver = {
|
|||
static char *mode_option __devinitdata = NULL;
|
||||
static int vram __devinitdata = 4;
|
||||
static int bpp __devinitdata = 8;
|
||||
static int mtrr __devinitdata;
|
||||
static int accel __devinitdata;
|
||||
static bool mtrr __devinitdata;
|
||||
static bool accel __devinitdata;
|
||||
static int hsync1 __devinitdata;
|
||||
static int hsync2 __devinitdata;
|
||||
static int vsync1 __devinitdata;
|
||||
|
@ -144,10 +144,10 @@ static int vsync2 __devinitdata;
|
|||
static int xres __devinitdata;
|
||||
static int yres;
|
||||
static int vyres __devinitdata;
|
||||
static int sync __devinitdata;
|
||||
static int extvga __devinitdata;
|
||||
static int dcolor __devinitdata;
|
||||
static int ddc3 __devinitdata = 2;
|
||||
static bool sync __devinitdata;
|
||||
static bool extvga __devinitdata;
|
||||
static bool dcolor __devinitdata;
|
||||
static bool ddc3 __devinitdata;
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
|
||||
|
@ -1776,7 +1776,7 @@ static void __devinit i810_init_defaults(struct i810fb_par *par,
|
|||
if (sync)
|
||||
par->dev_flags |= ALWAYS_SYNC;
|
||||
|
||||
par->ddc_num = ddc3;
|
||||
par->ddc_num = (ddc3 ? 3 : 2);
|
||||
|
||||
if (bpp < 8)
|
||||
bpp = 8;
|
||||
|
@ -1999,7 +1999,7 @@ static int __devinit i810fb_setup(char *options)
|
|||
else if (!strncmp(this_opt, "dcolor", 6))
|
||||
dcolor = 1;
|
||||
else if (!strncmp(this_opt, "ddc3", 4))
|
||||
ddc3 = 3;
|
||||
ddc3 = true;
|
||||
else
|
||||
mode_option = this_opt;
|
||||
}
|
||||
|
|
|
@ -147,7 +147,6 @@ static struct fb_var_screeninfo vesafb_defined = {
|
|||
39721L,48L,16L,33L,10L,
|
||||
96L,2L,~0, /* No sync info */
|
||||
FB_VMODE_NONINTERLACED,
|
||||
0, {0,0,0,0,0}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -593,7 +593,6 @@ static struct fb_var_screeninfo matroxfb_dh_defined = {
|
|||
39721L,48L,16L,33L,10L,
|
||||
96L,2,0, /* no sync info */
|
||||
FB_VMODE_NONINTERLACED,
|
||||
0, {0,0,0,0,0}
|
||||
};
|
||||
|
||||
static int matroxfb_dh_regit(const struct matrox_fb_info *minfo,
|
||||
|
|
|
@ -1053,18 +1053,7 @@ static struct platform_driver mbxfb_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
int __devinit mbxfb_init(void)
|
||||
{
|
||||
return platform_driver_register(&mbxfb_driver);
|
||||
}
|
||||
|
||||
static void __devexit mbxfb_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&mbxfb_driver);
|
||||
}
|
||||
|
||||
module_init(mbxfb_init);
|
||||
module_exit(mbxfb_exit);
|
||||
module_platform_driver(mbxfb_driver);
|
||||
|
||||
MODULE_DESCRIPTION("loadable framebuffer driver for Marathon device");
|
||||
MODULE_AUTHOR("Mike Rapoport, Compulab");
|
||||
|
|
|
@ -902,18 +902,7 @@ static struct platform_driver mxsfb_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init mxsfb_init(void)
|
||||
{
|
||||
return platform_driver_register(&mxsfb_driver);
|
||||
}
|
||||
|
||||
static void __exit mxsfb_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&mxsfb_driver);
|
||||
}
|
||||
|
||||
module_init(mxsfb_init);
|
||||
module_exit(mxsfb_exit);
|
||||
module_platform_driver(mxsfb_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Freescale mxs framebuffer driver");
|
||||
MODULE_AUTHOR("Sascha Hauer, Pengutronix");
|
||||
|
|
|
@ -762,18 +762,7 @@ static struct platform_driver nuc900fb_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
int __devinit nuc900fb_init(void)
|
||||
{
|
||||
return platform_driver_register(&nuc900fb_driver);
|
||||
}
|
||||
|
||||
static void __exit nuc900fb_cleanup(void)
|
||||
{
|
||||
platform_driver_unregister(&nuc900fb_driver);
|
||||
}
|
||||
|
||||
module_init(nuc900fb_init);
|
||||
module_exit(nuc900fb_cleanup);
|
||||
module_platform_driver(nuc900fb_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Framebuffer driver for the NUC900");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -198,7 +198,7 @@ static int ams_delta_panel_resume(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct platform_driver ams_delta_panel_driver = {
|
||||
static struct platform_driver ams_delta_panel_driver = {
|
||||
.probe = ams_delta_panel_probe,
|
||||
.remove = ams_delta_panel_remove,
|
||||
.suspend = ams_delta_panel_suspend,
|
||||
|
@ -209,15 +209,4 @@ struct platform_driver ams_delta_panel_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init ams_delta_panel_drv_init(void)
|
||||
{
|
||||
return platform_driver_register(&ams_delta_panel_driver);
|
||||
}
|
||||
|
||||
static void __exit ams_delta_panel_drv_cleanup(void)
|
||||
{
|
||||
platform_driver_unregister(&ams_delta_panel_driver);
|
||||
}
|
||||
|
||||
module_init(ams_delta_panel_drv_init);
|
||||
module_exit(ams_delta_panel_drv_cleanup);
|
||||
module_platform_driver(ams_delta_panel_driver);
|
||||
|
|
|
@ -113,7 +113,7 @@ static int h3_panel_resume(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct platform_driver h3_panel_driver = {
|
||||
static struct platform_driver h3_panel_driver = {
|
||||
.probe = h3_panel_probe,
|
||||
.remove = h3_panel_remove,
|
||||
.suspend = h3_panel_suspend,
|
||||
|
@ -124,16 +124,4 @@ struct platform_driver h3_panel_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init h3_panel_drv_init(void)
|
||||
{
|
||||
return platform_driver_register(&h3_panel_driver);
|
||||
}
|
||||
|
||||
static void __exit h3_panel_drv_cleanup(void)
|
||||
{
|
||||
platform_driver_unregister(&h3_panel_driver);
|
||||
}
|
||||
|
||||
module_init(h3_panel_drv_init);
|
||||
module_exit(h3_panel_drv_cleanup);
|
||||
|
||||
module_platform_driver(h3_panel_driver);
|
||||
|
|
|
@ -104,7 +104,7 @@ static int htcherald_panel_resume(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct platform_driver htcherald_panel_driver = {
|
||||
static struct platform_driver htcherald_panel_driver = {
|
||||
.probe = htcherald_panel_probe,
|
||||
.remove = htcherald_panel_remove,
|
||||
.suspend = htcherald_panel_suspend,
|
||||
|
@ -115,16 +115,4 @@ struct platform_driver htcherald_panel_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init htcherald_panel_drv_init(void)
|
||||
{
|
||||
return platform_driver_register(&htcherald_panel_driver);
|
||||
}
|
||||
|
||||
static void __exit htcherald_panel_drv_cleanup(void)
|
||||
{
|
||||
platform_driver_unregister(&htcherald_panel_driver);
|
||||
}
|
||||
|
||||
module_init(htcherald_panel_drv_init);
|
||||
module_exit(htcherald_panel_drv_cleanup);
|
||||
|
||||
module_platform_driver(htcherald_panel_driver);
|
||||
|
|
|
@ -98,7 +98,7 @@ static int innovator1510_panel_resume(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct platform_driver innovator1510_panel_driver = {
|
||||
static struct platform_driver innovator1510_panel_driver = {
|
||||
.probe = innovator1510_panel_probe,
|
||||
.remove = innovator1510_panel_remove,
|
||||
.suspend = innovator1510_panel_suspend,
|
||||
|
@ -109,16 +109,4 @@ struct platform_driver innovator1510_panel_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init innovator1510_panel_drv_init(void)
|
||||
{
|
||||
return platform_driver_register(&innovator1510_panel_driver);
|
||||
}
|
||||
|
||||
static void __exit innovator1510_panel_drv_cleanup(void)
|
||||
{
|
||||
platform_driver_unregister(&innovator1510_panel_driver);
|
||||
}
|
||||
|
||||
module_init(innovator1510_panel_drv_init);
|
||||
module_exit(innovator1510_panel_drv_cleanup);
|
||||
|
||||
module_platform_driver(innovator1510_panel_driver);
|
||||
|
|
|
@ -122,7 +122,7 @@ static int innovator1610_panel_resume(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct platform_driver innovator1610_panel_driver = {
|
||||
static struct platform_driver innovator1610_panel_driver = {
|
||||
.probe = innovator1610_panel_probe,
|
||||
.remove = innovator1610_panel_remove,
|
||||
.suspend = innovator1610_panel_suspend,
|
||||
|
@ -133,16 +133,4 @@ struct platform_driver innovator1610_panel_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init innovator1610_panel_drv_init(void)
|
||||
{
|
||||
return platform_driver_register(&innovator1610_panel_driver);
|
||||
}
|
||||
|
||||
static void __exit innovator1610_panel_drv_cleanup(void)
|
||||
{
|
||||
platform_driver_unregister(&innovator1610_panel_driver);
|
||||
}
|
||||
|
||||
module_init(innovator1610_panel_drv_init);
|
||||
module_exit(innovator1610_panel_drv_cleanup);
|
||||
|
||||
module_platform_driver(innovator1610_panel_driver);
|
||||
|
|
|
@ -603,7 +603,6 @@ static int mipid_spi_remove(struct spi_device *spi)
|
|||
static struct spi_driver mipid_spi_driver = {
|
||||
.driver = {
|
||||
.name = MIPID_MODULE_NAME,
|
||||
.bus = &spi_bus_type,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = mipid_spi_probe,
|
||||
|
|
|
@ -116,7 +116,7 @@ static int osk_panel_resume(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct platform_driver osk_panel_driver = {
|
||||
static struct platform_driver osk_panel_driver = {
|
||||
.probe = osk_panel_probe,
|
||||
.remove = osk_panel_remove,
|
||||
.suspend = osk_panel_suspend,
|
||||
|
@ -127,16 +127,4 @@ struct platform_driver osk_panel_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init osk_panel_drv_init(void)
|
||||
{
|
||||
return platform_driver_register(&osk_panel_driver);
|
||||
}
|
||||
|
||||
static void __exit osk_panel_drv_cleanup(void)
|
||||
{
|
||||
platform_driver_unregister(&osk_panel_driver);
|
||||
}
|
||||
|
||||
module_init(osk_panel_drv_init);
|
||||
module_exit(osk_panel_drv_cleanup);
|
||||
|
||||
module_platform_driver(osk_panel_driver);
|
||||
|
|
|
@ -97,7 +97,7 @@ static int palmte_panel_resume(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct platform_driver palmte_panel_driver = {
|
||||
static struct platform_driver palmte_panel_driver = {
|
||||
.probe = palmte_panel_probe,
|
||||
.remove = palmte_panel_remove,
|
||||
.suspend = palmte_panel_suspend,
|
||||
|
@ -108,16 +108,4 @@ struct platform_driver palmte_panel_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init palmte_panel_drv_init(void)
|
||||
{
|
||||
return platform_driver_register(&palmte_panel_driver);
|
||||
}
|
||||
|
||||
static void __exit palmte_panel_drv_cleanup(void)
|
||||
{
|
||||
platform_driver_unregister(&palmte_panel_driver);
|
||||
}
|
||||
|
||||
module_init(palmte_panel_drv_init);
|
||||
module_exit(palmte_panel_drv_cleanup);
|
||||
|
||||
module_platform_driver(palmte_panel_driver);
|
||||
|
|
|
@ -102,7 +102,7 @@ static int palmtt_panel_resume(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct platform_driver palmtt_panel_driver = {
|
||||
static struct platform_driver palmtt_panel_driver = {
|
||||
.probe = palmtt_panel_probe,
|
||||
.remove = palmtt_panel_remove,
|
||||
.suspend = palmtt_panel_suspend,
|
||||
|
@ -113,15 +113,4 @@ struct platform_driver palmtt_panel_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init palmtt_panel_drv_init(void)
|
||||
{
|
||||
return platform_driver_register(&palmtt_panel_driver);
|
||||
}
|
||||
|
||||
static void __exit palmtt_panel_drv_cleanup(void)
|
||||
{
|
||||
platform_driver_unregister(&palmtt_panel_driver);
|
||||
}
|
||||
|
||||
module_init(palmtt_panel_drv_init);
|
||||
module_exit(palmtt_panel_drv_cleanup);
|
||||
module_platform_driver(palmtt_panel_driver);
|
||||
|
|
|
@ -98,7 +98,7 @@ static int palmz71_panel_resume(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct platform_driver palmz71_panel_driver = {
|
||||
static struct platform_driver palmz71_panel_driver = {
|
||||
.probe = palmz71_panel_probe,
|
||||
.remove = palmz71_panel_remove,
|
||||
.suspend = palmz71_panel_suspend,
|
||||
|
@ -109,15 +109,4 @@ struct platform_driver palmz71_panel_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init palmz71_panel_drv_init(void)
|
||||
{
|
||||
return platform_driver_register(&palmz71_panel_driver);
|
||||
}
|
||||
|
||||
static void __exit palmz71_panel_drv_cleanup(void)
|
||||
{
|
||||
platform_driver_unregister(&palmz71_panel_driver);
|
||||
}
|
||||
|
||||
module_init(palmz71_panel_drv_init);
|
||||
module_exit(palmz71_panel_drv_cleanup);
|
||||
module_platform_driver(palmz71_panel_driver);
|
||||
|
|
|
@ -41,7 +41,7 @@ config PANEL_NEC_NL8048HL11_01B
|
|||
|
||||
config PANEL_PICODLP
|
||||
tristate "TI PICO DLP mini-projector"
|
||||
depends on OMAP2_DSS && I2C
|
||||
depends on OMAP2_DSS_DPI && I2C
|
||||
help
|
||||
A mini-projector used in TI's SDP4430 and EVM boards
|
||||
For more info please visit http://www.dlp.com/projector/
|
||||
|
|
|
@ -803,7 +803,6 @@ static int acx565akm_spi_remove(struct spi_device *spi)
|
|||
static struct spi_driver acx565akm_spi_driver = {
|
||||
.driver = {
|
||||
.name = "acx565akm",
|
||||
.bus = &spi_bus_type,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = acx565akm_spi_probe,
|
||||
|
|
|
@ -297,6 +297,72 @@ static struct panel_config generic_dpi_panels[] = {
|
|||
|
||||
.name = "apollon",
|
||||
},
|
||||
/* FocalTech ETM070003DH6 */
|
||||
{
|
||||
{
|
||||
.x_res = 800,
|
||||
.y_res = 480,
|
||||
|
||||
.pixel_clock = 28000,
|
||||
|
||||
.hsw = 48,
|
||||
.hfp = 40,
|
||||
.hbp = 40,
|
||||
|
||||
.vsw = 3,
|
||||
.vfp = 13,
|
||||
.vbp = 29,
|
||||
},
|
||||
.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
|
||||
OMAP_DSS_LCD_IHS,
|
||||
.name = "focaltech_etm070003dh6",
|
||||
},
|
||||
|
||||
/* Microtips Technologies - UMSH-8173MD */
|
||||
{
|
||||
{
|
||||
.x_res = 800,
|
||||
.y_res = 480,
|
||||
|
||||
.pixel_clock = 34560,
|
||||
|
||||
.hsw = 13,
|
||||
.hfp = 101,
|
||||
.hbp = 101,
|
||||
|
||||
.vsw = 23,
|
||||
.vfp = 1,
|
||||
.vbp = 1,
|
||||
},
|
||||
.acbi = 0x0,
|
||||
.acb = 0x0,
|
||||
.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
|
||||
OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IPC,
|
||||
.power_on_delay = 0,
|
||||
.power_off_delay = 0,
|
||||
.name = "microtips_umsh_8173md",
|
||||
},
|
||||
|
||||
/* OrtusTech COM43H4M10XTC */
|
||||
{
|
||||
{
|
||||
.x_res = 480,
|
||||
.y_res = 272,
|
||||
|
||||
.pixel_clock = 8000,
|
||||
|
||||
.hsw = 41,
|
||||
.hfp = 8,
|
||||
.hbp = 4,
|
||||
|
||||
.vsw = 10,
|
||||
.vfp = 4,
|
||||
.vbp = 2,
|
||||
},
|
||||
.config = OMAP_DSS_LCD_TFT,
|
||||
|
||||
.name = "ortustech_com43h4m10xtc",
|
||||
},
|
||||
};
|
||||
|
||||
struct panel_drv_data {
|
||||
|
|
|
@ -708,7 +708,6 @@ static int mipid_spi_remove(struct spi_device *spi)
|
|||
static struct spi_driver mipid_spi_driver = {
|
||||
.driver = {
|
||||
.name = "lcd_mipid",
|
||||
.bus = &spi_bus_type,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = mipid_spi_probe,
|
||||
|
|
|
@ -163,50 +163,93 @@ static void nec_8048_panel_remove(struct omap_dss_device *dssdev)
|
|||
kfree(necd);
|
||||
}
|
||||
|
||||
static int nec_8048_panel_enable(struct omap_dss_device *dssdev)
|
||||
static int nec_8048_panel_power_on(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r = 0;
|
||||
int r;
|
||||
struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev);
|
||||
struct backlight_device *bl = necd->bl;
|
||||
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
|
||||
return 0;
|
||||
|
||||
r = omapdss_dpi_display_enable(dssdev);
|
||||
if (r)
|
||||
goto err0;
|
||||
|
||||
if (dssdev->platform_enable) {
|
||||
r = dssdev->platform_enable(dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
r = nec_8048_bl_update_status(bl);
|
||||
if (r < 0)
|
||||
dev_err(&dssdev->dev, "failed to set lcd brightness\n");
|
||||
|
||||
r = omapdss_dpi_display_enable(dssdev);
|
||||
|
||||
return 0;
|
||||
err1:
|
||||
omapdss_dpi_display_disable(dssdev);
|
||||
err0:
|
||||
return r;
|
||||
}
|
||||
|
||||
static void nec_8048_panel_disable(struct omap_dss_device *dssdev)
|
||||
static void nec_8048_panel_power_off(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev);
|
||||
struct backlight_device *bl = necd->bl;
|
||||
|
||||
omapdss_dpi_display_disable(dssdev);
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
|
||||
return;
|
||||
|
||||
bl->props.brightness = 0;
|
||||
nec_8048_bl_update_status(bl);
|
||||
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
|
||||
omapdss_dpi_display_disable(dssdev);
|
||||
}
|
||||
|
||||
static int nec_8048_panel_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = nec_8048_panel_power_on(dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nec_8048_panel_disable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
nec_8048_panel_power_off(dssdev);
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
|
||||
}
|
||||
|
||||
static int nec_8048_panel_suspend(struct omap_dss_device *dssdev)
|
||||
{
|
||||
nec_8048_panel_disable(dssdev);
|
||||
nec_8048_panel_power_off(dssdev);
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nec_8048_panel_resume(struct omap_dss_device *dssdev)
|
||||
{
|
||||
return nec_8048_panel_enable(dssdev);
|
||||
int r;
|
||||
|
||||
r = nec_8048_panel_power_on(dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nec_8048_recommended_bpp(struct omap_dss_device *dssdev)
|
||||
|
@ -303,7 +346,6 @@ static struct spi_driver nec_8048_spi_driver = {
|
|||
.resume = nec_8048_spi_resume,
|
||||
.driver = {
|
||||
.name = "nec_8048_spi",
|
||||
.bus = &spi_bus_type,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -198,12 +198,6 @@ struct taal_data {
|
|||
bool te_enabled;
|
||||
|
||||
atomic_t do_update;
|
||||
struct {
|
||||
u16 x;
|
||||
u16 y;
|
||||
u16 w;
|
||||
u16 h;
|
||||
} update_region;
|
||||
int channel;
|
||||
|
||||
struct delayed_work te_timeout_work;
|
||||
|
@ -1188,6 +1182,10 @@ static int taal_power_on(struct omap_dss_device *dssdev)
|
|||
if (r)
|
||||
goto err;
|
||||
|
||||
r = dsi_enable_video_output(dssdev, td->channel);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
td->enabled = 1;
|
||||
|
||||
if (!td->intro_printed) {
|
||||
|
@ -1217,6 +1215,8 @@ static void taal_power_off(struct omap_dss_device *dssdev)
|
|||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
int r;
|
||||
|
||||
dsi_disable_video_output(dssdev, td->channel);
|
||||
|
||||
r = taal_dcs_write_0(td, MIPI_DCS_SET_DISPLAY_OFF);
|
||||
if (!r)
|
||||
r = taal_sleep_in(td);
|
||||
|
@ -1394,12 +1394,8 @@ static irqreturn_t taal_te_isr(int irq, void *data)
|
|||
if (old) {
|
||||
cancel_delayed_work(&td->te_timeout_work);
|
||||
|
||||
r = omap_dsi_update(dssdev, td->channel,
|
||||
td->update_region.x,
|
||||
td->update_region.y,
|
||||
td->update_region.w,
|
||||
td->update_region.h,
|
||||
taal_framedone_cb, dssdev);
|
||||
r = omap_dsi_update(dssdev, td->channel, taal_framedone_cb,
|
||||
dssdev);
|
||||
if (r)
|
||||
goto err;
|
||||
}
|
||||
|
@ -1444,26 +1440,20 @@ static int taal_update(struct omap_dss_device *dssdev,
|
|||
goto err;
|
||||
}
|
||||
|
||||
r = omap_dsi_prepare_update(dssdev, &x, &y, &w, &h, true);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
r = taal_set_update_window(td, x, y, w, h);
|
||||
/* XXX no need to send this every frame, but dsi break if not done */
|
||||
r = taal_set_update_window(td, 0, 0,
|
||||
td->panel_config->timings.x_res,
|
||||
td->panel_config->timings.y_res);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
if (td->te_enabled && panel_data->use_ext_te) {
|
||||
td->update_region.x = x;
|
||||
td->update_region.y = y;
|
||||
td->update_region.w = w;
|
||||
td->update_region.h = h;
|
||||
barrier();
|
||||
schedule_delayed_work(&td->te_timeout_work,
|
||||
msecs_to_jiffies(250));
|
||||
atomic_set(&td->do_update, 1);
|
||||
} else {
|
||||
r = omap_dsi_update(dssdev, td->channel, x, y, w, h,
|
||||
taal_framedone_cb, dssdev);
|
||||
r = omap_dsi_update(dssdev, td->channel, taal_framedone_cb,
|
||||
dssdev);
|
||||
if (r)
|
||||
goto err;
|
||||
}
|
||||
|
|
|
@ -512,7 +512,6 @@ static int __devexit tpo_td043_spi_remove(struct spi_device *spi)
|
|||
static struct spi_driver tpo_td043_spi_driver = {
|
||||
.driver = {
|
||||
.name = "tpo_td043mtea1_panel_spi",
|
||||
.bus = &spi_bus_type,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = tpo_td043_spi_probe,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
obj-$(CONFIG_OMAP2_DSS) += omapdss.o
|
||||
omapdss-y := core.o dss.o dss_features.o dispc.o display.o manager.o overlay.o
|
||||
omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \
|
||||
manager.o overlay.o apply.o
|
||||
omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
|
||||
omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
|
||||
omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
|
||||
|
|
1324
drivers/video/omap2/dss/apply.c
Normal file
1324
drivers/video/omap2/dss/apply.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -178,6 +178,8 @@ static int omap_dss_probe(struct platform_device *pdev)
|
|||
|
||||
dss_features_init();
|
||||
|
||||
dss_apply_init();
|
||||
|
||||
dss_init_overlay_managers(pdev);
|
||||
dss_init_overlays(pdev);
|
||||
|
||||
|
|
|
@ -64,22 +64,6 @@ struct omap_dispc_isr_data {
|
|||
u32 mask;
|
||||
};
|
||||
|
||||
struct dispc_h_coef {
|
||||
s8 hc4;
|
||||
s8 hc3;
|
||||
u8 hc2;
|
||||
s8 hc1;
|
||||
s8 hc0;
|
||||
};
|
||||
|
||||
struct dispc_v_coef {
|
||||
s8 vc22;
|
||||
s8 vc2;
|
||||
u8 vc1;
|
||||
s8 vc0;
|
||||
s8 vc00;
|
||||
};
|
||||
|
||||
enum omap_burst_size {
|
||||
BURST_SIZE_X2 = 0,
|
||||
BURST_SIZE_X4 = 1,
|
||||
|
@ -438,6 +422,34 @@ static struct omap_dss_device *dispc_mgr_get_device(enum omap_channel channel)
|
|||
return mgr ? mgr->device : NULL;
|
||||
}
|
||||
|
||||
u32 dispc_mgr_get_vsync_irq(enum omap_channel channel)
|
||||
{
|
||||
switch (channel) {
|
||||
case OMAP_DSS_CHANNEL_LCD:
|
||||
return DISPC_IRQ_VSYNC;
|
||||
case OMAP_DSS_CHANNEL_LCD2:
|
||||
return DISPC_IRQ_VSYNC2;
|
||||
case OMAP_DSS_CHANNEL_DIGIT:
|
||||
return DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
u32 dispc_mgr_get_framedone_irq(enum omap_channel channel)
|
||||
{
|
||||
switch (channel) {
|
||||
case OMAP_DSS_CHANNEL_LCD:
|
||||
return DISPC_IRQ_FRAMEDONE;
|
||||
case OMAP_DSS_CHANNEL_LCD2:
|
||||
return DISPC_IRQ_FRAMEDONE2;
|
||||
case OMAP_DSS_CHANNEL_DIGIT:
|
||||
return 0;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
bool dispc_mgr_go_busy(enum omap_channel channel)
|
||||
{
|
||||
int bit;
|
||||
|
@ -533,105 +545,27 @@ static void dispc_ovl_write_firv2_reg(enum omap_plane plane, int reg, u32 value)
|
|||
dispc_write_reg(DISPC_OVL_FIR_COEF_V2(plane, reg), value);
|
||||
}
|
||||
|
||||
static void dispc_ovl_set_scale_coef(enum omap_plane plane, int hscaleup,
|
||||
int vscaleup, int five_taps,
|
||||
enum omap_color_component color_comp)
|
||||
static void dispc_ovl_set_scale_coef(enum omap_plane plane, int fir_hinc,
|
||||
int fir_vinc, int five_taps,
|
||||
enum omap_color_component color_comp)
|
||||
{
|
||||
/* Coefficients for horizontal up-sampling */
|
||||
static const struct dispc_h_coef coef_hup[8] = {
|
||||
{ 0, 0, 128, 0, 0 },
|
||||
{ -1, 13, 124, -8, 0 },
|
||||
{ -2, 30, 112, -11, -1 },
|
||||
{ -5, 51, 95, -11, -2 },
|
||||
{ 0, -9, 73, 73, -9 },
|
||||
{ -2, -11, 95, 51, -5 },
|
||||
{ -1, -11, 112, 30, -2 },
|
||||
{ 0, -8, 124, 13, -1 },
|
||||
};
|
||||
|
||||
/* Coefficients for vertical up-sampling */
|
||||
static const struct dispc_v_coef coef_vup_3tap[8] = {
|
||||
{ 0, 0, 128, 0, 0 },
|
||||
{ 0, 3, 123, 2, 0 },
|
||||
{ 0, 12, 111, 5, 0 },
|
||||
{ 0, 32, 89, 7, 0 },
|
||||
{ 0, 0, 64, 64, 0 },
|
||||
{ 0, 7, 89, 32, 0 },
|
||||
{ 0, 5, 111, 12, 0 },
|
||||
{ 0, 2, 123, 3, 0 },
|
||||
};
|
||||
|
||||
static const struct dispc_v_coef coef_vup_5tap[8] = {
|
||||
{ 0, 0, 128, 0, 0 },
|
||||
{ -1, 13, 124, -8, 0 },
|
||||
{ -2, 30, 112, -11, -1 },
|
||||
{ -5, 51, 95, -11, -2 },
|
||||
{ 0, -9, 73, 73, -9 },
|
||||
{ -2, -11, 95, 51, -5 },
|
||||
{ -1, -11, 112, 30, -2 },
|
||||
{ 0, -8, 124, 13, -1 },
|
||||
};
|
||||
|
||||
/* Coefficients for horizontal down-sampling */
|
||||
static const struct dispc_h_coef coef_hdown[8] = {
|
||||
{ 0, 36, 56, 36, 0 },
|
||||
{ 4, 40, 55, 31, -2 },
|
||||
{ 8, 44, 54, 27, -5 },
|
||||
{ 12, 48, 53, 22, -7 },
|
||||
{ -9, 17, 52, 51, 17 },
|
||||
{ -7, 22, 53, 48, 12 },
|
||||
{ -5, 27, 54, 44, 8 },
|
||||
{ -2, 31, 55, 40, 4 },
|
||||
};
|
||||
|
||||
/* Coefficients for vertical down-sampling */
|
||||
static const struct dispc_v_coef coef_vdown_3tap[8] = {
|
||||
{ 0, 36, 56, 36, 0 },
|
||||
{ 0, 40, 57, 31, 0 },
|
||||
{ 0, 45, 56, 27, 0 },
|
||||
{ 0, 50, 55, 23, 0 },
|
||||
{ 0, 18, 55, 55, 0 },
|
||||
{ 0, 23, 55, 50, 0 },
|
||||
{ 0, 27, 56, 45, 0 },
|
||||
{ 0, 31, 57, 40, 0 },
|
||||
};
|
||||
|
||||
static const struct dispc_v_coef coef_vdown_5tap[8] = {
|
||||
{ 0, 36, 56, 36, 0 },
|
||||
{ 4, 40, 55, 31, -2 },
|
||||
{ 8, 44, 54, 27, -5 },
|
||||
{ 12, 48, 53, 22, -7 },
|
||||
{ -9, 17, 52, 51, 17 },
|
||||
{ -7, 22, 53, 48, 12 },
|
||||
{ -5, 27, 54, 44, 8 },
|
||||
{ -2, 31, 55, 40, 4 },
|
||||
};
|
||||
|
||||
const struct dispc_h_coef *h_coef;
|
||||
const struct dispc_v_coef *v_coef;
|
||||
const struct dispc_coef *h_coef, *v_coef;
|
||||
int i;
|
||||
|
||||
if (hscaleup)
|
||||
h_coef = coef_hup;
|
||||
else
|
||||
h_coef = coef_hdown;
|
||||
|
||||
if (vscaleup)
|
||||
v_coef = five_taps ? coef_vup_5tap : coef_vup_3tap;
|
||||
else
|
||||
v_coef = five_taps ? coef_vdown_5tap : coef_vdown_3tap;
|
||||
h_coef = dispc_ovl_get_scale_coef(fir_hinc, true);
|
||||
v_coef = dispc_ovl_get_scale_coef(fir_vinc, five_taps);
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
u32 h, hv;
|
||||
|
||||
h = FLD_VAL(h_coef[i].hc0, 7, 0)
|
||||
| FLD_VAL(h_coef[i].hc1, 15, 8)
|
||||
| FLD_VAL(h_coef[i].hc2, 23, 16)
|
||||
| FLD_VAL(h_coef[i].hc3, 31, 24);
|
||||
hv = FLD_VAL(h_coef[i].hc4, 7, 0)
|
||||
| FLD_VAL(v_coef[i].vc0, 15, 8)
|
||||
| FLD_VAL(v_coef[i].vc1, 23, 16)
|
||||
| FLD_VAL(v_coef[i].vc2, 31, 24);
|
||||
h = FLD_VAL(h_coef[i].hc0_vc00, 7, 0)
|
||||
| FLD_VAL(h_coef[i].hc1_vc0, 15, 8)
|
||||
| FLD_VAL(h_coef[i].hc2_vc1, 23, 16)
|
||||
| FLD_VAL(h_coef[i].hc3_vc2, 31, 24);
|
||||
hv = FLD_VAL(h_coef[i].hc4_vc22, 7, 0)
|
||||
| FLD_VAL(v_coef[i].hc1_vc0, 15, 8)
|
||||
| FLD_VAL(v_coef[i].hc2_vc1, 23, 16)
|
||||
| FLD_VAL(v_coef[i].hc3_vc2, 31, 24);
|
||||
|
||||
if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y) {
|
||||
dispc_ovl_write_firh_reg(plane, i, h);
|
||||
|
@ -646,8 +580,8 @@ static void dispc_ovl_set_scale_coef(enum omap_plane plane, int hscaleup,
|
|||
if (five_taps) {
|
||||
for (i = 0; i < 8; i++) {
|
||||
u32 v;
|
||||
v = FLD_VAL(v_coef[i].vc00, 7, 0)
|
||||
| FLD_VAL(v_coef[i].vc22, 15, 8);
|
||||
v = FLD_VAL(v_coef[i].hc0_vc00, 7, 0)
|
||||
| FLD_VAL(v_coef[i].hc4_vc22, 15, 8);
|
||||
if (color_comp == DISPC_COLOR_COMPONENT_RGB_Y)
|
||||
dispc_ovl_write_firv_reg(plane, i, v);
|
||||
else
|
||||
|
@ -875,8 +809,7 @@ static void dispc_ovl_set_color_mode(enum omap_plane plane,
|
|||
REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
|
||||
}
|
||||
|
||||
static void dispc_ovl_set_channel_out(enum omap_plane plane,
|
||||
enum omap_channel channel)
|
||||
void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel)
|
||||
{
|
||||
int shift;
|
||||
u32 val;
|
||||
|
@ -923,6 +856,39 @@ static void dispc_ovl_set_channel_out(enum omap_plane plane,
|
|||
dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val);
|
||||
}
|
||||
|
||||
static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane)
|
||||
{
|
||||
int shift;
|
||||
u32 val;
|
||||
enum omap_channel channel;
|
||||
|
||||
switch (plane) {
|
||||
case OMAP_DSS_GFX:
|
||||
shift = 8;
|
||||
break;
|
||||
case OMAP_DSS_VIDEO1:
|
||||
case OMAP_DSS_VIDEO2:
|
||||
case OMAP_DSS_VIDEO3:
|
||||
shift = 16;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
val = dispc_read_reg(DISPC_OVL_ATTRIBUTES(plane));
|
||||
|
||||
if (dss_has_feature(FEAT_MGR_LCD2)) {
|
||||
if (FLD_GET(val, 31, 30) == 0)
|
||||
channel = FLD_GET(val, shift, shift);
|
||||
else
|
||||
channel = OMAP_DSS_CHANNEL_LCD2;
|
||||
} else {
|
||||
channel = FLD_GET(val, shift, shift);
|
||||
}
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
static void dispc_ovl_set_burst_size(enum omap_plane plane,
|
||||
enum omap_burst_size burst_size)
|
||||
{
|
||||
|
@ -964,7 +930,7 @@ void dispc_enable_gamma_table(bool enable)
|
|||
REG_FLD_MOD(DISPC_CONFIG, enable, 9, 9);
|
||||
}
|
||||
|
||||
void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable)
|
||||
static void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable)
|
||||
{
|
||||
u16 reg;
|
||||
|
||||
|
@ -978,7 +944,7 @@ void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable)
|
|||
REG_FLD_MOD(reg, enable, 15, 15);
|
||||
}
|
||||
|
||||
void dispc_mgr_set_cpr_coef(enum omap_channel channel,
|
||||
static void dispc_mgr_set_cpr_coef(enum omap_channel channel,
|
||||
struct omap_dss_cpr_coefs *coefs)
|
||||
{
|
||||
u32 coef_r, coef_g, coef_b;
|
||||
|
@ -1057,8 +1023,7 @@ u32 dispc_ovl_get_fifo_size(enum omap_plane plane)
|
|||
return dispc.fifo_size[plane];
|
||||
}
|
||||
|
||||
static void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low,
|
||||
u32 high)
|
||||
void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high)
|
||||
{
|
||||
u8 hi_start, hi_end, lo_start, lo_end;
|
||||
u32 unit;
|
||||
|
@ -1169,17 +1134,12 @@ static void dispc_ovl_set_scale_param(enum omap_plane plane,
|
|||
enum omap_color_component color_comp)
|
||||
{
|
||||
int fir_hinc, fir_vinc;
|
||||
int hscaleup, vscaleup;
|
||||
|
||||
hscaleup = orig_width <= out_width;
|
||||
vscaleup = orig_height <= out_height;
|
||||
|
||||
dispc_ovl_set_scale_coef(plane, hscaleup, vscaleup, five_taps,
|
||||
color_comp);
|
||||
|
||||
fir_hinc = 1024 * orig_width / out_width;
|
||||
fir_vinc = 1024 * orig_height / out_height;
|
||||
|
||||
dispc_ovl_set_scale_coef(plane, fir_hinc, fir_vinc, five_taps,
|
||||
color_comp);
|
||||
dispc_ovl_set_fir(plane, fir_hinc, fir_vinc, color_comp);
|
||||
}
|
||||
|
||||
|
@ -1654,6 +1614,9 @@ static unsigned long calc_fclk_five_taps(enum omap_channel channel, u16 width,
|
|||
u32 fclk = 0;
|
||||
u64 tmp, pclk = dispc_mgr_pclk_rate(channel);
|
||||
|
||||
if (height <= out_height && width <= out_width)
|
||||
return (unsigned long) pclk;
|
||||
|
||||
if (height > out_height) {
|
||||
struct omap_dss_device *dssdev = dispc_mgr_get_device(channel);
|
||||
unsigned int ppl = dssdev->panel.timings.x_res;
|
||||
|
@ -1708,7 +1671,16 @@ static unsigned long calc_fclk(enum omap_channel channel, u16 width,
|
|||
else
|
||||
vf = 1;
|
||||
|
||||
return dispc_mgr_pclk_rate(channel) * vf * hf;
|
||||
if (cpu_is_omap24xx()) {
|
||||
if (vf > 1 && hf > 1)
|
||||
return dispc_mgr_pclk_rate(channel) * 4;
|
||||
else
|
||||
return dispc_mgr_pclk_rate(channel) * 2;
|
||||
} else if (cpu_is_omap34xx()) {
|
||||
return dispc_mgr_pclk_rate(channel) * vf * hf;
|
||||
} else {
|
||||
return dispc_mgr_pclk_rate(channel) * hf;
|
||||
}
|
||||
}
|
||||
|
||||
static int dispc_ovl_calc_scaling(enum omap_plane plane,
|
||||
|
@ -1718,6 +1690,8 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
|
|||
{
|
||||
struct omap_overlay *ovl = omap_dss_get_overlay(plane);
|
||||
const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
|
||||
const int maxsinglelinewidth =
|
||||
dss_feat_get_param_max(FEAT_PARAM_LINEWIDTH);
|
||||
unsigned long fclk = 0;
|
||||
|
||||
if (width == out_width && height == out_height)
|
||||
|
@ -1734,28 +1708,40 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
|
|||
out_height > height * 8)
|
||||
return -EINVAL;
|
||||
|
||||
/* Must use 5-tap filter? */
|
||||
*five_taps = height > out_height * 2;
|
||||
|
||||
if (!*five_taps) {
|
||||
if (cpu_is_omap24xx()) {
|
||||
if (width > maxsinglelinewidth)
|
||||
DSSERR("Cannot scale max input width exceeded");
|
||||
*five_taps = false;
|
||||
fclk = calc_fclk(channel, width, height, out_width,
|
||||
out_height);
|
||||
} else if (cpu_is_omap34xx()) {
|
||||
if (width > (maxsinglelinewidth * 2)) {
|
||||
DSSERR("Cannot setup scaling");
|
||||
DSSERR("width exceeds maximum width possible");
|
||||
return -EINVAL;
|
||||
}
|
||||
fclk = calc_fclk_five_taps(channel, width, height, out_width,
|
||||
out_height, color_mode);
|
||||
if (width > maxsinglelinewidth) {
|
||||
if (height > out_height && height < out_height * 2)
|
||||
*five_taps = false;
|
||||
else {
|
||||
DSSERR("cannot setup scaling with five taps");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
if (!*five_taps)
|
||||
fclk = calc_fclk(channel, width, height, out_width,
|
||||
out_height);
|
||||
} else {
|
||||
if (width > maxsinglelinewidth) {
|
||||
DSSERR("Cannot scale width exceeds max line width");
|
||||
return -EINVAL;
|
||||
}
|
||||
fclk = calc_fclk(channel, width, height, out_width,
|
||||
out_height);
|
||||
|
||||
/* Try 5-tap filter if 3-tap fclk is too high */
|
||||
if (cpu_is_omap34xx() && height > out_height &&
|
||||
fclk > dispc_fclk_rate())
|
||||
*five_taps = true;
|
||||
}
|
||||
|
||||
if (width > (2048 >> *five_taps)) {
|
||||
DSSERR("failed to set up scaling, fclk too low\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (*five_taps)
|
||||
fclk = calc_fclk_five_taps(channel, width, height,
|
||||
out_width, out_height, color_mode);
|
||||
|
||||
DSSDBG("required fclk rate = %lu Hz\n", fclk);
|
||||
DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate());
|
||||
|
||||
|
@ -1771,11 +1757,10 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
|
|||
}
|
||||
|
||||
int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
|
||||
bool ilace, enum omap_channel channel, bool replication,
|
||||
u32 fifo_low, u32 fifo_high)
|
||||
bool ilace, bool replication)
|
||||
{
|
||||
struct omap_overlay *ovl = omap_dss_get_overlay(plane);
|
||||
bool five_taps = false;
|
||||
bool five_taps = true;
|
||||
bool fieldmode = 0;
|
||||
int r, cconv = 0;
|
||||
unsigned offset0, offset1;
|
||||
|
@ -1783,36 +1768,43 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
|
|||
s32 pix_inc;
|
||||
u16 frame_height = oi->height;
|
||||
unsigned int field_offset = 0;
|
||||
u16 outw, outh;
|
||||
enum omap_channel channel;
|
||||
|
||||
channel = dispc_ovl_get_channel_out(plane);
|
||||
|
||||
DSSDBG("dispc_ovl_setup %d, pa %x, pa_uv %x, sw %d, %d,%d, %dx%d -> "
|
||||
"%dx%d, cmode %x, rot %d, mir %d, ilace %d chan %d repl %d "
|
||||
"fifo_low %d fifo high %d\n", plane, oi->paddr, oi->p_uv_addr,
|
||||
"%dx%d, cmode %x, rot %d, mir %d, ilace %d chan %d repl %d\n",
|
||||
plane, oi->paddr, oi->p_uv_addr,
|
||||
oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
|
||||
oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
|
||||
oi->mirror, ilace, channel, replication, fifo_low, fifo_high);
|
||||
oi->mirror, ilace, channel, replication);
|
||||
|
||||
if (oi->paddr == 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (ilace && oi->height == oi->out_height)
|
||||
outw = oi->out_width == 0 ? oi->width : oi->out_width;
|
||||
outh = oi->out_height == 0 ? oi->height : oi->out_height;
|
||||
|
||||
if (ilace && oi->height == outh)
|
||||
fieldmode = 1;
|
||||
|
||||
if (ilace) {
|
||||
if (fieldmode)
|
||||
oi->height /= 2;
|
||||
oi->pos_y /= 2;
|
||||
oi->out_height /= 2;
|
||||
outh /= 2;
|
||||
|
||||
DSSDBG("adjusting for ilace: height %d, pos_y %d, "
|
||||
"out_height %d\n",
|
||||
oi->height, oi->pos_y, oi->out_height);
|
||||
oi->height, oi->pos_y, outh);
|
||||
}
|
||||
|
||||
if (!dss_feat_color_mode_supported(plane, oi->color_mode))
|
||||
return -EINVAL;
|
||||
|
||||
r = dispc_ovl_calc_scaling(plane, channel, oi->width, oi->height,
|
||||
oi->out_width, oi->out_height, oi->color_mode,
|
||||
outw, outh, oi->color_mode,
|
||||
&five_taps);
|
||||
if (r)
|
||||
return r;
|
||||
|
@ -1830,10 +1822,10 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
|
|||
* so the integer part must be added to the base address of the
|
||||
* bottom field.
|
||||
*/
|
||||
if (!oi->height || oi->height == oi->out_height)
|
||||
if (!oi->height || oi->height == outh)
|
||||
field_offset = 0;
|
||||
else
|
||||
field_offset = oi->height / oi->out_height / 2;
|
||||
field_offset = oi->height / outh / 2;
|
||||
}
|
||||
|
||||
/* Fields are independent but interleaved in memory. */
|
||||
|
@ -1869,7 +1861,7 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
|
|||
dispc_ovl_set_pix_inc(plane, pix_inc);
|
||||
|
||||
DSSDBG("%d,%d %dx%d -> %dx%d\n", oi->pos_x, oi->pos_y, oi->width,
|
||||
oi->height, oi->out_width, oi->out_height);
|
||||
oi->height, outw, outh);
|
||||
|
||||
dispc_ovl_set_pos(plane, oi->pos_x, oi->pos_y);
|
||||
|
||||
|
@ -1877,10 +1869,10 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
|
|||
|
||||
if (ovl->caps & OMAP_DSS_OVL_CAP_SCALE) {
|
||||
dispc_ovl_set_scaling(plane, oi->width, oi->height,
|
||||
oi->out_width, oi->out_height,
|
||||
outw, outh,
|
||||
ilace, five_taps, fieldmode,
|
||||
oi->color_mode, oi->rotation);
|
||||
dispc_ovl_set_vid_size(plane, oi->out_width, oi->out_height);
|
||||
dispc_ovl_set_vid_size(plane, outw, outh);
|
||||
dispc_ovl_set_vid_color_conv(plane, cconv);
|
||||
}
|
||||
|
||||
|
@ -1891,10 +1883,7 @@ int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
|
|||
dispc_ovl_set_pre_mult_alpha(plane, oi->pre_mult_alpha);
|
||||
dispc_ovl_setup_global_alpha(plane, oi->global_alpha);
|
||||
|
||||
dispc_ovl_set_channel_out(plane, channel);
|
||||
|
||||
dispc_ovl_enable_replication(plane, replication);
|
||||
dispc_ovl_set_fifo_threshold(plane, fifo_low, fifo_high);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1916,10 +1905,14 @@ static void dispc_disable_isr(void *data, u32 mask)
|
|||
|
||||
static void _enable_lcd_out(enum omap_channel channel, bool enable)
|
||||
{
|
||||
if (channel == OMAP_DSS_CHANNEL_LCD2)
|
||||
if (channel == OMAP_DSS_CHANNEL_LCD2) {
|
||||
REG_FLD_MOD(DISPC_CONTROL2, enable ? 1 : 0, 0, 0);
|
||||
else
|
||||
/* flush posted write */
|
||||
dispc_read_reg(DISPC_CONTROL2);
|
||||
} else {
|
||||
REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0);
|
||||
dispc_read_reg(DISPC_CONTROL);
|
||||
}
|
||||
}
|
||||
|
||||
static void dispc_mgr_enable_lcd_out(enum omap_channel channel, bool enable)
|
||||
|
@ -1967,6 +1960,8 @@ static void dispc_mgr_enable_lcd_out(enum omap_channel channel, bool enable)
|
|||
static void _enable_digit_out(bool enable)
|
||||
{
|
||||
REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1);
|
||||
/* flush posted write */
|
||||
dispc_read_reg(DISPC_CONTROL);
|
||||
}
|
||||
|
||||
static void dispc_mgr_enable_digit_out(bool enable)
|
||||
|
@ -2124,25 +2119,12 @@ void dispc_set_loadmode(enum omap_dss_load_mode mode)
|
|||
}
|
||||
|
||||
|
||||
void dispc_mgr_set_default_color(enum omap_channel channel, u32 color)
|
||||
static void dispc_mgr_set_default_color(enum omap_channel channel, u32 color)
|
||||
{
|
||||
dispc_write_reg(DISPC_DEFAULT_COLOR(channel), color);
|
||||
}
|
||||
|
||||
u32 dispc_mgr_get_default_color(enum omap_channel channel)
|
||||
{
|
||||
u32 l;
|
||||
|
||||
BUG_ON(channel != OMAP_DSS_CHANNEL_DIGIT &&
|
||||
channel != OMAP_DSS_CHANNEL_LCD &&
|
||||
channel != OMAP_DSS_CHANNEL_LCD2);
|
||||
|
||||
l = dispc_read_reg(DISPC_DEFAULT_COLOR(channel));
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
void dispc_mgr_set_trans_key(enum omap_channel ch,
|
||||
static void dispc_mgr_set_trans_key(enum omap_channel ch,
|
||||
enum omap_dss_trans_key_type type,
|
||||
u32 trans_key)
|
||||
{
|
||||
|
@ -2156,26 +2138,7 @@ void dispc_mgr_set_trans_key(enum omap_channel ch,
|
|||
dispc_write_reg(DISPC_TRANS_COLOR(ch), trans_key);
|
||||
}
|
||||
|
||||
void dispc_mgr_get_trans_key(enum omap_channel ch,
|
||||
enum omap_dss_trans_key_type *type,
|
||||
u32 *trans_key)
|
||||
{
|
||||
if (type) {
|
||||
if (ch == OMAP_DSS_CHANNEL_LCD)
|
||||
*type = REG_GET(DISPC_CONFIG, 11, 11);
|
||||
else if (ch == OMAP_DSS_CHANNEL_DIGIT)
|
||||
*type = REG_GET(DISPC_CONFIG, 13, 13);
|
||||
else if (ch == OMAP_DSS_CHANNEL_LCD2)
|
||||
*type = REG_GET(DISPC_CONFIG2, 11, 11);
|
||||
else
|
||||
BUG();
|
||||
}
|
||||
|
||||
if (trans_key)
|
||||
*trans_key = dispc_read_reg(DISPC_TRANS_COLOR(ch));
|
||||
}
|
||||
|
||||
void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable)
|
||||
static void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable)
|
||||
{
|
||||
if (ch == OMAP_DSS_CHANNEL_LCD)
|
||||
REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10);
|
||||
|
@ -2185,7 +2148,8 @@ void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable)
|
|||
REG_FLD_MOD(DISPC_CONFIG2, enable, 10, 10);
|
||||
}
|
||||
|
||||
void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable)
|
||||
static void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch,
|
||||
bool enable)
|
||||
{
|
||||
if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
|
||||
return;
|
||||
|
@ -2196,40 +2160,20 @@ void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable)
|
|||
REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19);
|
||||
}
|
||||
|
||||
bool dispc_mgr_alpha_fixed_zorder_enabled(enum omap_channel ch)
|
||||
void dispc_mgr_setup(enum omap_channel channel,
|
||||
struct omap_overlay_manager_info *info)
|
||||
{
|
||||
bool enabled;
|
||||
|
||||
if (!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER))
|
||||
return false;
|
||||
|
||||
if (ch == OMAP_DSS_CHANNEL_LCD)
|
||||
enabled = REG_GET(DISPC_CONFIG, 18, 18);
|
||||
else if (ch == OMAP_DSS_CHANNEL_DIGIT)
|
||||
enabled = REG_GET(DISPC_CONFIG, 19, 19);
|
||||
else
|
||||
BUG();
|
||||
|
||||
return enabled;
|
||||
dispc_mgr_set_default_color(channel, info->default_color);
|
||||
dispc_mgr_set_trans_key(channel, info->trans_key_type, info->trans_key);
|
||||
dispc_mgr_enable_trans_key(channel, info->trans_enabled);
|
||||
dispc_mgr_enable_alpha_fixed_zorder(channel,
|
||||
info->partial_alpha_enabled);
|
||||
if (dss_has_feature(FEAT_CPR)) {
|
||||
dispc_mgr_enable_cpr(channel, info->cpr_enable);
|
||||
dispc_mgr_set_cpr_coef(channel, &info->cpr_coefs);
|
||||
}
|
||||
}
|
||||
|
||||
bool dispc_mgr_trans_key_enabled(enum omap_channel ch)
|
||||
{
|
||||
bool enabled;
|
||||
|
||||
if (ch == OMAP_DSS_CHANNEL_LCD)
|
||||
enabled = REG_GET(DISPC_CONFIG, 10, 10);
|
||||
else if (ch == OMAP_DSS_CHANNEL_DIGIT)
|
||||
enabled = REG_GET(DISPC_CONFIG, 12, 12);
|
||||
else if (ch == OMAP_DSS_CHANNEL_LCD2)
|
||||
enabled = REG_GET(DISPC_CONFIG2, 10, 10);
|
||||
else
|
||||
BUG();
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
|
||||
void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines)
|
||||
{
|
||||
int code;
|
||||
|
@ -3184,7 +3128,8 @@ static void dispc_error_worker(struct work_struct *work)
|
|||
for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) {
|
||||
struct omap_overlay_manager *mgr;
|
||||
mgr = omap_dss_get_overlay_manager(i);
|
||||
mgr->device->driver->disable(mgr->device);
|
||||
if (mgr->device && mgr->device->driver)
|
||||
mgr->device->driver->disable(mgr->device);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -97,6 +97,17 @@
|
|||
#define DISPC_OVL_PRELOAD(n) (DISPC_OVL_BASE(n) + \
|
||||
DISPC_PRELOAD_OFFSET(n))
|
||||
|
||||
/* DISPC up/downsampling FIR filter coefficient structure */
|
||||
struct dispc_coef {
|
||||
s8 hc4_vc22;
|
||||
s8 hc3_vc2;
|
||||
u8 hc2_vc1;
|
||||
s8 hc1_vc0;
|
||||
s8 hc0_vc00;
|
||||
};
|
||||
|
||||
const struct dispc_coef *dispc_ovl_get_scale_coef(int inc, int five_taps);
|
||||
|
||||
/* DISPC manager/channel specific registers */
|
||||
static inline u16 DISPC_DEFAULT_COLOR(enum omap_channel channel)
|
||||
{
|
||||
|
|
326
drivers/video/omap2/dss/dispc_coefs.c
Normal file
326
drivers/video/omap2/dss/dispc_coefs.c
Normal file
|
@ -0,0 +1,326 @@
|
|||
/*
|
||||
* linux/drivers/video/omap2/dss/dispc_coefs.c
|
||||
*
|
||||
* Copyright (C) 2011 Texas Instruments
|
||||
* Author: Chandrabhanu Mahapatra <cmahapatra@ti.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <video/omapdss.h>
|
||||
#include "dispc.h"
|
||||
|
||||
#define ARRAY_LEN(array) (sizeof(array) / sizeof(array[0]))
|
||||
|
||||
static const struct dispc_coef coef3_M8[8] = {
|
||||
{ 0, 0, 128, 0, 0 },
|
||||
{ 0, -4, 123, 9, 0 },
|
||||
{ 0, -4, 108, 87, 0 },
|
||||
{ 0, -2, 87, 43, 0 },
|
||||
{ 0, 64, 64, 0, 0 },
|
||||
{ 0, 43, 87, -2, 0 },
|
||||
{ 0, 24, 108, -4, 0 },
|
||||
{ 0, 9, 123, -4, 0 },
|
||||
};
|
||||
|
||||
static const struct dispc_coef coef3_M9[8] = {
|
||||
{ 0, 6, 116, 6, 0 },
|
||||
{ 0, 0, 112, 16, 0 },
|
||||
{ 0, -2, 100, 30, 0 },
|
||||
{ 0, -2, 83, 47, 0 },
|
||||
{ 0, 64, 64, 0, 0 },
|
||||
{ 0, 47, 83, -2, 0 },
|
||||
{ 0, 30, 100, -2, 0 },
|
||||
{ 0, 16, 112, 0, 0 },
|
||||
};
|
||||
|
||||
static const struct dispc_coef coef3_M10[8] = {
|
||||
{ 0, 10, 108, 10, 0 },
|
||||
{ 0, 3, 104, 21, 0 },
|
||||
{ 0, 0, 94, 34, 0 },
|
||||
{ 0, -1, 80, 49, 0 },
|
||||
{ 0, 64, 64, 0, 0 },
|
||||
{ 0, 49, 80, -1, 0 },
|
||||
{ 0, 34, 94, 0, 0 },
|
||||
{ 0, 21, 104, 3, 0 },
|
||||
};
|
||||
|
||||
static const struct dispc_coef coef3_M11[8] = {
|
||||
{ 0, 14, 100, 14, 0 },
|
||||
{ 0, 6, 98, 24, 0 },
|
||||
{ 0, 2, 90, 36, 0 },
|
||||
{ 0, 0, 78, 50, 0 },
|
||||
{ 0, 64, 64, 0, 0 },
|
||||
{ 0, 50, 78, 0, 0 },
|
||||
{ 0, 36, 90, 2, 0 },
|
||||
{ 0, 24, 98, 6, 0 },
|
||||
};
|
||||
|
||||
static const struct dispc_coef coef3_M12[8] = {
|
||||
{ 0, 16, 96, 16, 0 },
|
||||
{ 0, 9, 93, 26, 0 },
|
||||
{ 0, 4, 86, 38, 0 },
|
||||
{ 0, 1, 76, 51, 0 },
|
||||
{ 0, 64, 64, 0, 0 },
|
||||
{ 0, 51, 76, 1, 0 },
|
||||
{ 0, 38, 86, 4, 0 },
|
||||
{ 0, 26, 93, 9, 0 },
|
||||
};
|
||||
|
||||
static const struct dispc_coef coef3_M13[8] = {
|
||||
{ 0, 18, 92, 18, 0 },
|
||||
{ 0, 10, 90, 28, 0 },
|
||||
{ 0, 5, 83, 40, 0 },
|
||||
{ 0, 1, 75, 52, 0 },
|
||||
{ 0, 64, 64, 0, 0 },
|
||||
{ 0, 52, 75, 1, 0 },
|
||||
{ 0, 40, 83, 5, 0 },
|
||||
{ 0, 28, 90, 10, 0 },
|
||||
};
|
||||
|
||||
static const struct dispc_coef coef3_M14[8] = {
|
||||
{ 0, 20, 88, 20, 0 },
|
||||
{ 0, 12, 86, 30, 0 },
|
||||
{ 0, 6, 81, 41, 0 },
|
||||
{ 0, 2, 74, 52, 0 },
|
||||
{ 0, 64, 64, 0, 0 },
|
||||
{ 0, 52, 74, 2, 0 },
|
||||
{ 0, 41, 81, 6, 0 },
|
||||
{ 0, 30, 86, 12, 0 },
|
||||
};
|
||||
|
||||
static const struct dispc_coef coef3_M16[8] = {
|
||||
{ 0, 22, 84, 22, 0 },
|
||||
{ 0, 14, 82, 32, 0 },
|
||||
{ 0, 8, 78, 42, 0 },
|
||||
{ 0, 3, 72, 53, 0 },
|
||||
{ 0, 64, 64, 0, 0 },
|
||||
{ 0, 53, 72, 3, 0 },
|
||||
{ 0, 42, 78, 8, 0 },
|
||||
{ 0, 32, 82, 14, 0 },
|
||||
};
|
||||
|
||||
static const struct dispc_coef coef3_M19[8] = {
|
||||
{ 0, 24, 80, 24, 0 },
|
||||
{ 0, 16, 79, 33, 0 },
|
||||
{ 0, 9, 76, 43, 0 },
|
||||
{ 0, 4, 70, 54, 0 },
|
||||
{ 0, 64, 64, 0, 0 },
|
||||
{ 0, 54, 70, 4, 0 },
|
||||
{ 0, 43, 76, 9, 0 },
|
||||
{ 0, 33, 79, 16, 0 },
|
||||
};
|
||||
|
||||
static const struct dispc_coef coef3_M22[8] = {
|
||||
{ 0, 25, 78, 25, 0 },
|
||||
{ 0, 17, 77, 34, 0 },
|
||||
{ 0, 10, 74, 44, 0 },
|
||||
{ 0, 5, 69, 54, 0 },
|
||||
{ 0, 64, 64, 0, 0 },
|
||||
{ 0, 54, 69, 5, 0 },
|
||||
{ 0, 44, 74, 10, 0 },
|
||||
{ 0, 34, 77, 17, 0 },
|
||||
};
|
||||
|
||||
static const struct dispc_coef coef3_M26[8] = {
|
||||
{ 0, 26, 76, 26, 0 },
|
||||
{ 0, 19, 74, 35, 0 },
|
||||
{ 0, 11, 72, 45, 0 },
|
||||
{ 0, 5, 69, 54, 0 },
|
||||
{ 0, 64, 64, 0, 0 },
|
||||
{ 0, 54, 69, 5, 0 },
|
||||
{ 0, 45, 72, 11, 0 },
|
||||
{ 0, 35, 74, 19, 0 },
|
||||
};
|
||||
|
||||
static const struct dispc_coef coef3_M32[8] = {
|
||||
{ 0, 27, 74, 27, 0 },
|
||||
{ 0, 19, 73, 36, 0 },
|
||||
{ 0, 12, 71, 45, 0 },
|
||||
{ 0, 6, 68, 54, 0 },
|
||||
{ 0, 64, 64, 0, 0 },
|
||||
{ 0, 54, 68, 6, 0 },
|
||||
{ 0, 45, 71, 12, 0 },
|
||||
{ 0, 36, 73, 19, 0 },
|
||||
};
|
||||
|
||||
static const struct dispc_coef coef5_M8[8] = {
|
||||
{ 0, 0, 128, 0, 0 },
|
||||
{ -2, 14, 125, -10, 1 },
|
||||
{ -6, 33, 114, -15, 2 },
|
||||
{ -10, 55, 98, -16, 1 },
|
||||
{ 0, -14, 78, 78, -14 },
|
||||
{ 1, -16, 98, 55, -10 },
|
||||
{ 2, -15, 114, 33, -6 },
|
||||
{ 1, -10, 125, 14, -2 },
|
||||
};
|
||||
|
||||
static const struct dispc_coef coef5_M9[8] = {
|
||||
{ -3, 10, 114, 10, -3 },
|
||||
{ -6, 24, 110, 0, -1 },
|
||||
{ -8, 40, 103, -7, 0 },
|
||||
{ -11, 58, 91, -11, 1 },
|
||||
{ 0, -12, 76, 76, -12 },
|
||||
{ 1, -11, 91, 58, -11 },
|
||||
{ 0, -7, 103, 40, -8 },
|
||||
{ -1, 0, 111, 24, -6 },
|
||||
};
|
||||
|
||||
static const struct dispc_coef coef5_M10[8] = {
|
||||
{ -4, 18, 100, 18, -4 },
|
||||
{ -6, 30, 99, 8, -3 },
|
||||
{ -8, 44, 93, 0, -1 },
|
||||
{ -9, 58, 84, -5, 0 },
|
||||
{ 0, -8, 72, 72, -8 },
|
||||
{ 0, -5, 84, 58, -9 },
|
||||
{ -1, 0, 93, 44, -8 },
|
||||
{ -3, 8, 99, 30, -6 },
|
||||
};
|
||||
|
||||
static const struct dispc_coef coef5_M11[8] = {
|
||||
{ -5, 23, 92, 23, -5 },
|
||||
{ -6, 34, 90, 13, -3 },
|
||||
{ -6, 45, 85, 6, -2 },
|
||||
{ -6, 57, 78, 0, -1 },
|
||||
{ 0, -4, 68, 68, -4 },
|
||||
{ -1, 0, 78, 57, -6 },
|
||||
{ -2, 6, 85, 45, -6 },
|
||||
{ -3, 13, 90, 34, -6 },
|
||||
};
|
||||
|
||||
static const struct dispc_coef coef5_M12[8] = {
|
||||
{ -4, 26, 84, 26, -4 },
|
||||
{ -5, 36, 82, 18, -3 },
|
||||
{ -4, 46, 78, 10, -2 },
|
||||
{ -3, 55, 72, 5, -1 },
|
||||
{ 0, 0, 64, 64, 0 },
|
||||
{ -1, 5, 72, 55, -3 },
|
||||
{ -2, 10, 78, 46, -4 },
|
||||
{ -3, 18, 82, 36, -5 },
|
||||
};
|
||||
|
||||
static const struct dispc_coef coef5_M13[8] = {
|
||||
{ -3, 28, 78, 28, -3 },
|
||||
{ -3, 37, 76, 21, -3 },
|
||||
{ -2, 45, 73, 14, -2 },
|
||||
{ 0, 53, 68, 8, -1 },
|
||||
{ 0, 3, 61, 61, 3 },
|
||||
{ -1, 8, 68, 53, 0 },
|
||||
{ -2, 14, 73, 45, -2 },
|
||||
{ -3, 21, 76, 37, -3 },
|
||||
};
|
||||
|
||||
static const struct dispc_coef coef5_M14[8] = {
|
||||
{ -2, 30, 72, 30, -2 },
|
||||
{ -1, 37, 71, 23, -2 },
|
||||
{ 0, 45, 69, 16, -2 },
|
||||
{ 3, 52, 64, 10, -1 },
|
||||
{ 0, 6, 58, 58, 6 },
|
||||
{ -1, 10, 64, 52, 3 },
|
||||
{ -2, 16, 69, 45, 0 },
|
||||
{ -2, 23, 71, 37, -1 },
|
||||
};
|
||||
|
||||
static const struct dispc_coef coef5_M16[8] = {
|
||||
{ 0, 31, 66, 31, 0 },
|
||||
{ 1, 38, 65, 25, -1 },
|
||||
{ 3, 44, 62, 20, -1 },
|
||||
{ 6, 49, 59, 14, 0 },
|
||||
{ 0, 10, 54, 54, 10 },
|
||||
{ 0, 14, 59, 49, 6 },
|
||||
{ -1, 20, 62, 44, 3 },
|
||||
{ -1, 25, 65, 38, 1 },
|
||||
};
|
||||
|
||||
static const struct dispc_coef coef5_M19[8] = {
|
||||
{ 3, 32, 58, 32, 3 },
|
||||
{ 4, 38, 58, 27, 1 },
|
||||
{ 7, 42, 55, 23, 1 },
|
||||
{ 10, 46, 54, 18, 0 },
|
||||
{ 0, 14, 50, 50, 14 },
|
||||
{ 0, 18, 54, 46, 10 },
|
||||
{ 1, 23, 55, 42, 7 },
|
||||
{ 1, 27, 58, 38, 4 },
|
||||
};
|
||||
|
||||
static const struct dispc_coef coef5_M22[8] = {
|
||||
{ 4, 33, 54, 33, 4 },
|
||||
{ 6, 37, 54, 28, 3 },
|
||||
{ 9, 41, 53, 24, 1 },
|
||||
{ 12, 45, 51, 20, 0 },
|
||||
{ 0, 16, 48, 48, 16 },
|
||||
{ 0, 20, 51, 45, 12 },
|
||||
{ 1, 24, 53, 41, 9 },
|
||||
{ 3, 28, 54, 37, 6 },
|
||||
};
|
||||
|
||||
static const struct dispc_coef coef5_M26[8] = {
|
||||
{ 6, 33, 50, 33, 6 },
|
||||
{ 8, 36, 51, 29, 4 },
|
||||
{ 11, 40, 50, 25, 2 },
|
||||
{ 14, 43, 48, 22, 1 },
|
||||
{ 0, 18, 46, 46, 18 },
|
||||
{ 1, 22, 48, 43, 14 },
|
||||
{ 2, 25, 50, 40, 11 },
|
||||
{ 4, 29, 51, 36, 8 },
|
||||
};
|
||||
|
||||
static const struct dispc_coef coef5_M32[8] = {
|
||||
{ 7, 33, 48, 33, 7 },
|
||||
{ 10, 36, 48, 29, 5 },
|
||||
{ 13, 39, 47, 26, 3 },
|
||||
{ 16, 42, 46, 23, 1 },
|
||||
{ 0, 19, 45, 45, 19 },
|
||||
{ 1, 23, 46, 42, 16 },
|
||||
{ 3, 26, 47, 39, 13 },
|
||||
{ 5, 29, 48, 36, 10 },
|
||||
};
|
||||
|
||||
const struct dispc_coef *dispc_ovl_get_scale_coef(int inc, int five_taps)
|
||||
{
|
||||
int i;
|
||||
static const struct {
|
||||
int Mmin;
|
||||
int Mmax;
|
||||
const struct dispc_coef *coef_3;
|
||||
const struct dispc_coef *coef_5;
|
||||
} coefs[] = {
|
||||
{ 27, 32, coef3_M32, coef5_M32 },
|
||||
{ 23, 26, coef3_M26, coef5_M26 },
|
||||
{ 20, 22, coef3_M22, coef5_M22 },
|
||||
{ 17, 19, coef3_M19, coef5_M19 },
|
||||
{ 15, 16, coef3_M16, coef5_M16 },
|
||||
{ 14, 14, coef3_M14, coef5_M14 },
|
||||
{ 13, 13, coef3_M13, coef5_M13 },
|
||||
{ 12, 12, coef3_M12, coef5_M12 },
|
||||
{ 11, 11, coef3_M11, coef5_M11 },
|
||||
{ 10, 10, coef3_M10, coef5_M10 },
|
||||
{ 9, 9, coef3_M9, coef5_M9 },
|
||||
{ 4, 8, coef3_M8, coef5_M8 },
|
||||
/*
|
||||
* When upscaling more than two times, blockiness and outlines
|
||||
* around the image are observed when M8 tables are used. M11,
|
||||
* M16 and M19 tables are used to prevent this.
|
||||
*/
|
||||
{ 3, 3, coef3_M11, coef5_M11 },
|
||||
{ 2, 2, coef3_M16, coef5_M16 },
|
||||
{ 0, 1, coef3_M19, coef5_M19 },
|
||||
};
|
||||
|
||||
inc /= 128;
|
||||
for (i = 0; i < ARRAY_LEN(coefs); ++i)
|
||||
if (inc >= coefs[i].Mmin && inc <= coefs[i].Mmax)
|
||||
return five_taps ? coefs[i].coef_5 : coefs[i].coef_3;
|
||||
return NULL;
|
||||
}
|
|
@ -223,10 +223,13 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
|
|||
|
||||
mdelay(2);
|
||||
|
||||
dssdev->manager->enable(dssdev->manager);
|
||||
r = dss_mgr_enable(dssdev->manager);
|
||||
if (r)
|
||||
goto err_mgr_enable;
|
||||
|
||||
return 0;
|
||||
|
||||
err_mgr_enable:
|
||||
err_set_mode:
|
||||
if (dpi_use_dsi_pll(dssdev))
|
||||
dsi_pll_uninit(dpi.dsidev, true);
|
||||
|
@ -249,7 +252,7 @@ EXPORT_SYMBOL(omapdss_dpi_display_enable);
|
|||
|
||||
void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
dssdev->manager->disable(dssdev->manager);
|
||||
dss_mgr_disable(dssdev->manager);
|
||||
|
||||
if (dpi_use_dsi_pll(dssdev)) {
|
||||
dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK);
|
||||
|
|
|
@ -203,6 +203,21 @@ struct dsi_reg { u16 idx; };
|
|||
typedef void (*omap_dsi_isr_t) (void *arg, u32 mask);
|
||||
|
||||
#define DSI_MAX_NR_ISRS 2
|
||||
#define DSI_MAX_NR_LANES 5
|
||||
|
||||
enum dsi_lane_function {
|
||||
DSI_LANE_UNUSED = 0,
|
||||
DSI_LANE_CLK,
|
||||
DSI_LANE_DATA1,
|
||||
DSI_LANE_DATA2,
|
||||
DSI_LANE_DATA3,
|
||||
DSI_LANE_DATA4,
|
||||
};
|
||||
|
||||
struct dsi_lane_config {
|
||||
enum dsi_lane_function function;
|
||||
u8 polarity;
|
||||
};
|
||||
|
||||
struct dsi_isr_data {
|
||||
omap_dsi_isr_t isr;
|
||||
|
@ -223,24 +238,6 @@ enum dsi_vc_source {
|
|||
DSI_VC_SOURCE_VP,
|
||||
};
|
||||
|
||||
enum dsi_lane {
|
||||
DSI_CLK_P = 1 << 0,
|
||||
DSI_CLK_N = 1 << 1,
|
||||
DSI_DATA1_P = 1 << 2,
|
||||
DSI_DATA1_N = 1 << 3,
|
||||
DSI_DATA2_P = 1 << 4,
|
||||
DSI_DATA2_N = 1 << 5,
|
||||
DSI_DATA3_P = 1 << 6,
|
||||
DSI_DATA3_N = 1 << 7,
|
||||
DSI_DATA4_P = 1 << 8,
|
||||
DSI_DATA4_N = 1 << 9,
|
||||
};
|
||||
|
||||
struct dsi_update_region {
|
||||
u16 x, y, w, h;
|
||||
struct omap_dss_device *device;
|
||||
};
|
||||
|
||||
struct dsi_irq_stats {
|
||||
unsigned long last_reset;
|
||||
unsigned irq_count;
|
||||
|
@ -290,7 +287,9 @@ struct dsi_data {
|
|||
struct dsi_isr_tables isr_tables_copy;
|
||||
|
||||
int update_channel;
|
||||
struct dsi_update_region update_region;
|
||||
#ifdef DEBUG
|
||||
unsigned update_bytes;
|
||||
#endif
|
||||
|
||||
bool te_enabled;
|
||||
bool ulps_enabled;
|
||||
|
@ -327,7 +326,10 @@ struct dsi_data {
|
|||
unsigned long fint_min, fint_max;
|
||||
unsigned long lpdiv_max;
|
||||
|
||||
int num_data_lanes;
|
||||
unsigned num_lanes_supported;
|
||||
|
||||
struct dsi_lane_config lanes[DSI_MAX_NR_LANES];
|
||||
unsigned num_lanes_used;
|
||||
|
||||
unsigned scp_clk_refcount;
|
||||
};
|
||||
|
@ -413,14 +415,29 @@ static void dsi_completion_handler(void *data, u32 mask)
|
|||
static inline int wait_for_bit_change(struct platform_device *dsidev,
|
||||
const struct dsi_reg idx, int bitnum, int value)
|
||||
{
|
||||
int t = 100000;
|
||||
unsigned long timeout;
|
||||
ktime_t wait;
|
||||
int t;
|
||||
|
||||
while (REG_GET(dsidev, idx, bitnum, bitnum) != value) {
|
||||
if (--t == 0)
|
||||
return !value;
|
||||
/* first busyloop to see if the bit changes right away */
|
||||
t = 100;
|
||||
while (t-- > 0) {
|
||||
if (REG_GET(dsidev, idx, bitnum, bitnum) == value)
|
||||
return value;
|
||||
}
|
||||
|
||||
return value;
|
||||
/* then loop for 500ms, sleeping for 1ms in between */
|
||||
timeout = jiffies + msecs_to_jiffies(500);
|
||||
while (time_before(jiffies, timeout)) {
|
||||
if (REG_GET(dsidev, idx, bitnum, bitnum) == value)
|
||||
return value;
|
||||
|
||||
wait = ns_to_ktime(1000 * 1000);
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
schedule_hrtimeout(&wait, HRTIMER_MODE_REL);
|
||||
}
|
||||
|
||||
return !value;
|
||||
}
|
||||
|
||||
u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt)
|
||||
|
@ -454,7 +471,6 @@ static void dsi_perf_mark_start(struct platform_device *dsidev)
|
|||
static void dsi_perf_show(struct platform_device *dsidev, const char *name)
|
||||
{
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
struct omap_dss_device *dssdev = dsi->update_region.device;
|
||||
ktime_t t, setup_time, trans_time;
|
||||
u32 total_bytes;
|
||||
u32 setup_us, trans_us, total_us;
|
||||
|
@ -476,9 +492,7 @@ static void dsi_perf_show(struct platform_device *dsidev, const char *name)
|
|||
|
||||
total_us = setup_us + trans_us;
|
||||
|
||||
total_bytes = dsi->update_region.w *
|
||||
dsi->update_region.h *
|
||||
dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8;
|
||||
total_bytes = dsi->update_bytes;
|
||||
|
||||
printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), "
|
||||
"%u bytes, %u kbytes/sec\n",
|
||||
|
@ -1720,17 +1734,19 @@ static void dsi_dump_dsidev_clocks(struct platform_device *dsidev,
|
|||
seq_printf(s, "CLKIN4DDR\t%-16luregm %u\n",
|
||||
cinfo->clkin4ddr, cinfo->regm);
|
||||
|
||||
seq_printf(s, "%s (%s)\t%-16luregm_dispc %u\t(%s)\n",
|
||||
dss_get_generic_clk_source_name(dispc_clk_src),
|
||||
dss_feat_get_clk_source_name(dispc_clk_src),
|
||||
seq_printf(s, "DSI_PLL_HSDIV_DISPC (%s)\t%-16luregm_dispc %u\t(%s)\n",
|
||||
dss_feat_get_clk_source_name(dsi_module == 0 ?
|
||||
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC :
|
||||
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC),
|
||||
cinfo->dsi_pll_hsdiv_dispc_clk,
|
||||
cinfo->regm_dispc,
|
||||
dispc_clk_src == OMAP_DSS_CLK_SRC_FCK ?
|
||||
"off" : "on");
|
||||
|
||||
seq_printf(s, "%s (%s)\t%-16luregm_dsi %u\t(%s)\n",
|
||||
dss_get_generic_clk_source_name(dsi_clk_src),
|
||||
dss_feat_get_clk_source_name(dsi_clk_src),
|
||||
seq_printf(s, "DSI_PLL_HSDIV_DSI (%s)\t%-16luregm_dsi %u\t(%s)\n",
|
||||
dss_feat_get_clk_source_name(dsi_module == 0 ?
|
||||
OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI :
|
||||
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI),
|
||||
cinfo->dsi_pll_hsdiv_dsi_clk,
|
||||
cinfo->regm_dsi,
|
||||
dsi_clk_src == OMAP_DSS_CLK_SRC_FCK ?
|
||||
|
@ -2029,34 +2045,6 @@ static int dsi_cio_power(struct platform_device *dsidev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Number of data lanes present on DSI interface */
|
||||
static inline int dsi_get_num_data_lanes(struct platform_device *dsidev)
|
||||
{
|
||||
/* DSI on OMAP3 doesn't have register DSI_GNQ, set number
|
||||
* of data lanes as 2 by default */
|
||||
if (dss_has_feature(FEAT_DSI_GNQ))
|
||||
return REG_GET(dsidev, DSI_GNQ, 11, 9); /* NB_DATA_LANES */
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* Number of data lanes used by the dss device */
|
||||
static inline int dsi_get_num_data_lanes_dssdev(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int num_data_lanes = 0;
|
||||
|
||||
if (dssdev->phy.dsi.data1_lane != 0)
|
||||
num_data_lanes++;
|
||||
if (dssdev->phy.dsi.data2_lane != 0)
|
||||
num_data_lanes++;
|
||||
if (dssdev->phy.dsi.data3_lane != 0)
|
||||
num_data_lanes++;
|
||||
if (dssdev->phy.dsi.data4_lane != 0)
|
||||
num_data_lanes++;
|
||||
|
||||
return num_data_lanes;
|
||||
}
|
||||
|
||||
static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)
|
||||
{
|
||||
int val;
|
||||
|
@ -2088,59 +2076,112 @@ static unsigned dsi_get_line_buf_size(struct platform_device *dsidev)
|
|||
}
|
||||
}
|
||||
|
||||
static void dsi_set_lane_config(struct omap_dss_device *dssdev)
|
||||
static int dsi_parse_lane_config(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
|
||||
u32 r;
|
||||
int num_data_lanes_dssdev = dsi_get_num_data_lanes_dssdev(dssdev);
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
u8 lanes[DSI_MAX_NR_LANES];
|
||||
u8 polarities[DSI_MAX_NR_LANES];
|
||||
int num_lanes, i;
|
||||
|
||||
int clk_lane = dssdev->phy.dsi.clk_lane;
|
||||
int data1_lane = dssdev->phy.dsi.data1_lane;
|
||||
int data2_lane = dssdev->phy.dsi.data2_lane;
|
||||
int clk_pol = dssdev->phy.dsi.clk_pol;
|
||||
int data1_pol = dssdev->phy.dsi.data1_pol;
|
||||
int data2_pol = dssdev->phy.dsi.data2_pol;
|
||||
static const enum dsi_lane_function functions[] = {
|
||||
DSI_LANE_CLK,
|
||||
DSI_LANE_DATA1,
|
||||
DSI_LANE_DATA2,
|
||||
DSI_LANE_DATA3,
|
||||
DSI_LANE_DATA4,
|
||||
};
|
||||
|
||||
lanes[0] = dssdev->phy.dsi.clk_lane;
|
||||
lanes[1] = dssdev->phy.dsi.data1_lane;
|
||||
lanes[2] = dssdev->phy.dsi.data2_lane;
|
||||
lanes[3] = dssdev->phy.dsi.data3_lane;
|
||||
lanes[4] = dssdev->phy.dsi.data4_lane;
|
||||
polarities[0] = dssdev->phy.dsi.clk_pol;
|
||||
polarities[1] = dssdev->phy.dsi.data1_pol;
|
||||
polarities[2] = dssdev->phy.dsi.data2_pol;
|
||||
polarities[3] = dssdev->phy.dsi.data3_pol;
|
||||
polarities[4] = dssdev->phy.dsi.data4_pol;
|
||||
|
||||
num_lanes = 0;
|
||||
|
||||
for (i = 0; i < dsi->num_lanes_supported; ++i)
|
||||
dsi->lanes[i].function = DSI_LANE_UNUSED;
|
||||
|
||||
for (i = 0; i < dsi->num_lanes_supported; ++i) {
|
||||
int num;
|
||||
|
||||
if (lanes[i] == DSI_LANE_UNUSED)
|
||||
break;
|
||||
|
||||
num = lanes[i] - 1;
|
||||
|
||||
if (num >= dsi->num_lanes_supported)
|
||||
return -EINVAL;
|
||||
|
||||
if (dsi->lanes[num].function != DSI_LANE_UNUSED)
|
||||
return -EINVAL;
|
||||
|
||||
dsi->lanes[num].function = functions[i];
|
||||
dsi->lanes[num].polarity = polarities[i];
|
||||
num_lanes++;
|
||||
}
|
||||
|
||||
if (num_lanes < 2 || num_lanes > dsi->num_lanes_supported)
|
||||
return -EINVAL;
|
||||
|
||||
dsi->num_lanes_used = num_lanes;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dsi_set_lane_config(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
static const u8 offsets[] = { 0, 4, 8, 12, 16 };
|
||||
static const enum dsi_lane_function functions[] = {
|
||||
DSI_LANE_CLK,
|
||||
DSI_LANE_DATA1,
|
||||
DSI_LANE_DATA2,
|
||||
DSI_LANE_DATA3,
|
||||
DSI_LANE_DATA4,
|
||||
};
|
||||
u32 r;
|
||||
int i;
|
||||
|
||||
r = dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG1);
|
||||
r = FLD_MOD(r, clk_lane, 2, 0);
|
||||
r = FLD_MOD(r, clk_pol, 3, 3);
|
||||
r = FLD_MOD(r, data1_lane, 6, 4);
|
||||
r = FLD_MOD(r, data1_pol, 7, 7);
|
||||
r = FLD_MOD(r, data2_lane, 10, 8);
|
||||
r = FLD_MOD(r, data2_pol, 11, 11);
|
||||
if (num_data_lanes_dssdev > 2) {
|
||||
int data3_lane = dssdev->phy.dsi.data3_lane;
|
||||
int data3_pol = dssdev->phy.dsi.data3_pol;
|
||||
|
||||
r = FLD_MOD(r, data3_lane, 14, 12);
|
||||
r = FLD_MOD(r, data3_pol, 15, 15);
|
||||
}
|
||||
if (num_data_lanes_dssdev > 3) {
|
||||
int data4_lane = dssdev->phy.dsi.data4_lane;
|
||||
int data4_pol = dssdev->phy.dsi.data4_pol;
|
||||
for (i = 0; i < dsi->num_lanes_used; ++i) {
|
||||
unsigned offset = offsets[i];
|
||||
unsigned polarity, lane_number;
|
||||
unsigned t;
|
||||
|
||||
r = FLD_MOD(r, data4_lane, 18, 16);
|
||||
r = FLD_MOD(r, data4_pol, 19, 19);
|
||||
for (t = 0; t < dsi->num_lanes_supported; ++t)
|
||||
if (dsi->lanes[t].function == functions[i])
|
||||
break;
|
||||
|
||||
if (t == dsi->num_lanes_supported)
|
||||
return -EINVAL;
|
||||
|
||||
lane_number = t;
|
||||
polarity = dsi->lanes[t].polarity;
|
||||
|
||||
r = FLD_MOD(r, lane_number + 1, offset + 2, offset);
|
||||
r = FLD_MOD(r, polarity, offset + 3, offset + 3);
|
||||
}
|
||||
|
||||
/* clear the unused lanes */
|
||||
for (; i < dsi->num_lanes_supported; ++i) {
|
||||
unsigned offset = offsets[i];
|
||||
|
||||
r = FLD_MOD(r, 0, offset + 2, offset);
|
||||
r = FLD_MOD(r, 0, offset + 3, offset + 3);
|
||||
}
|
||||
|
||||
dsi_write_reg(dsidev, DSI_COMPLEXIO_CFG1, r);
|
||||
|
||||
/* The configuration of the DSI complex I/O (number of data lanes,
|
||||
position, differential order) should not be changed while
|
||||
DSS.DSI_CLK_CRTRL[20] LP_CLK_ENABLE bit is set to 1. In order for
|
||||
the hardware to take into account a new configuration of the complex
|
||||
I/O (done in DSS.DSI_COMPLEXIO_CFG1 register), it is recommended to
|
||||
follow this sequence: First set the DSS.DSI_CTRL[0] IF_EN bit to 1,
|
||||
then reset the DSS.DSI_CTRL[0] IF_EN to 0, then set
|
||||
DSS.DSI_CLK_CTRL[20] LP_CLK_ENABLE to 1 and finally set again the
|
||||
DSS.DSI_CTRL[0] IF_EN bit to 1. If the sequence is not followed, the
|
||||
DSI complex I/O configuration is unknown. */
|
||||
|
||||
/*
|
||||
REG_FLD_MOD(dsidev, DSI_CTRL, 1, 0, 0);
|
||||
REG_FLD_MOD(dsidev, DSI_CTRL, 0, 0, 0);
|
||||
REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 1, 20, 20);
|
||||
REG_FLD_MOD(dsidev, DSI_CTRL, 1, 0, 0);
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline unsigned ns2ddr(struct platform_device *dsidev, unsigned ns)
|
||||
|
@ -2230,49 +2271,28 @@ static void dsi_cio_timings(struct platform_device *dsidev)
|
|||
dsi_write_reg(dsidev, DSI_DSIPHY_CFG2, r);
|
||||
}
|
||||
|
||||
/* lane masks have lane 0 at lsb. mask_p for positive lines, n for negative */
|
||||
static void dsi_cio_enable_lane_override(struct omap_dss_device *dssdev,
|
||||
enum dsi_lane lanes)
|
||||
unsigned mask_p, unsigned mask_n)
|
||||
{
|
||||
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
int clk_lane = dssdev->phy.dsi.clk_lane;
|
||||
int data1_lane = dssdev->phy.dsi.data1_lane;
|
||||
int data2_lane = dssdev->phy.dsi.data2_lane;
|
||||
int data3_lane = dssdev->phy.dsi.data3_lane;
|
||||
int data4_lane = dssdev->phy.dsi.data4_lane;
|
||||
int clk_pol = dssdev->phy.dsi.clk_pol;
|
||||
int data1_pol = dssdev->phy.dsi.data1_pol;
|
||||
int data2_pol = dssdev->phy.dsi.data2_pol;
|
||||
int data3_pol = dssdev->phy.dsi.data3_pol;
|
||||
int data4_pol = dssdev->phy.dsi.data4_pol;
|
||||
int i;
|
||||
u32 l;
|
||||
u8 lptxscp_start = dsi->num_lanes_supported == 3 ? 22 : 26;
|
||||
|
||||
u32 l = 0;
|
||||
u8 lptxscp_start = dsi->num_data_lanes == 2 ? 22 : 26;
|
||||
l = 0;
|
||||
|
||||
if (lanes & DSI_CLK_P)
|
||||
l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 0 : 1));
|
||||
if (lanes & DSI_CLK_N)
|
||||
l |= 1 << ((clk_lane - 1) * 2 + (clk_pol ? 1 : 0));
|
||||
for (i = 0; i < dsi->num_lanes_supported; ++i) {
|
||||
unsigned p = dsi->lanes[i].polarity;
|
||||
|
||||
if (lanes & DSI_DATA1_P)
|
||||
l |= 1 << ((data1_lane - 1) * 2 + (data1_pol ? 0 : 1));
|
||||
if (lanes & DSI_DATA1_N)
|
||||
l |= 1 << ((data1_lane - 1) * 2 + (data1_pol ? 1 : 0));
|
||||
if (mask_p & (1 << i))
|
||||
l |= 1 << (i * 2 + (p ? 0 : 1));
|
||||
|
||||
if (lanes & DSI_DATA2_P)
|
||||
l |= 1 << ((data2_lane - 1) * 2 + (data2_pol ? 0 : 1));
|
||||
if (lanes & DSI_DATA2_N)
|
||||
l |= 1 << ((data2_lane - 1) * 2 + (data2_pol ? 1 : 0));
|
||||
if (mask_n & (1 << i))
|
||||
l |= 1 << (i * 2 + (p ? 1 : 0));
|
||||
}
|
||||
|
||||
if (lanes & DSI_DATA3_P)
|
||||
l |= 1 << ((data3_lane - 1) * 2 + (data3_pol ? 0 : 1));
|
||||
if (lanes & DSI_DATA3_N)
|
||||
l |= 1 << ((data3_lane - 1) * 2 + (data3_pol ? 1 : 0));
|
||||
|
||||
if (lanes & DSI_DATA4_P)
|
||||
l |= 1 << ((data4_lane - 1) * 2 + (data4_pol ? 0 : 1));
|
||||
if (lanes & DSI_DATA4_N)
|
||||
l |= 1 << ((data4_lane - 1) * 2 + (data4_pol ? 1 : 0));
|
||||
/*
|
||||
* Bits in REGLPTXSCPDAT4TO0DXDY:
|
||||
* 17: DY0 18: DX0
|
||||
|
@ -2305,51 +2325,40 @@ static void dsi_cio_disable_lane_override(struct platform_device *dsidev)
|
|||
static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
|
||||
int t;
|
||||
int bits[3];
|
||||
bool in_use[3];
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
int t, i;
|
||||
bool in_use[DSI_MAX_NR_LANES];
|
||||
static const u8 offsets_old[] = { 28, 27, 26 };
|
||||
static const u8 offsets_new[] = { 24, 25, 26, 27, 28 };
|
||||
const u8 *offsets;
|
||||
|
||||
if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC)) {
|
||||
bits[0] = 28;
|
||||
bits[1] = 27;
|
||||
bits[2] = 26;
|
||||
} else {
|
||||
bits[0] = 24;
|
||||
bits[1] = 25;
|
||||
bits[2] = 26;
|
||||
}
|
||||
if (dss_has_feature(FEAT_DSI_REVERSE_TXCLKESC))
|
||||
offsets = offsets_old;
|
||||
else
|
||||
offsets = offsets_new;
|
||||
|
||||
in_use[0] = false;
|
||||
in_use[1] = false;
|
||||
in_use[2] = false;
|
||||
|
||||
if (dssdev->phy.dsi.clk_lane != 0)
|
||||
in_use[dssdev->phy.dsi.clk_lane - 1] = true;
|
||||
if (dssdev->phy.dsi.data1_lane != 0)
|
||||
in_use[dssdev->phy.dsi.data1_lane - 1] = true;
|
||||
if (dssdev->phy.dsi.data2_lane != 0)
|
||||
in_use[dssdev->phy.dsi.data2_lane - 1] = true;
|
||||
for (i = 0; i < dsi->num_lanes_supported; ++i)
|
||||
in_use[i] = dsi->lanes[i].function != DSI_LANE_UNUSED;
|
||||
|
||||
t = 100000;
|
||||
while (true) {
|
||||
u32 l;
|
||||
int i;
|
||||
int ok;
|
||||
|
||||
l = dsi_read_reg(dsidev, DSI_DSIPHY_CFG5);
|
||||
|
||||
ok = 0;
|
||||
for (i = 0; i < 3; ++i) {
|
||||
if (!in_use[i] || (l & (1 << bits[i])))
|
||||
for (i = 0; i < dsi->num_lanes_supported; ++i) {
|
||||
if (!in_use[i] || (l & (1 << offsets[i])))
|
||||
ok++;
|
||||
}
|
||||
|
||||
if (ok == 3)
|
||||
if (ok == dsi->num_lanes_supported)
|
||||
break;
|
||||
|
||||
if (--t == 0) {
|
||||
for (i = 0; i < 3; ++i) {
|
||||
if (!in_use[i] || (l & (1 << bits[i])))
|
||||
for (i = 0; i < dsi->num_lanes_supported; ++i) {
|
||||
if (!in_use[i] || (l & (1 << offsets[i])))
|
||||
continue;
|
||||
|
||||
DSSERR("CIO TXCLKESC%d domain not coming " \
|
||||
|
@ -2362,22 +2371,20 @@ static int dsi_cio_wait_tx_clk_esc_reset(struct omap_dss_device *dssdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* return bitmask of enabled lanes, lane0 being the lsb */
|
||||
static unsigned dsi_get_lane_mask(struct omap_dss_device *dssdev)
|
||||
{
|
||||
unsigned lanes = 0;
|
||||
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
unsigned mask = 0;
|
||||
int i;
|
||||
|
||||
if (dssdev->phy.dsi.clk_lane != 0)
|
||||
lanes |= 1 << (dssdev->phy.dsi.clk_lane - 1);
|
||||
if (dssdev->phy.dsi.data1_lane != 0)
|
||||
lanes |= 1 << (dssdev->phy.dsi.data1_lane - 1);
|
||||
if (dssdev->phy.dsi.data2_lane != 0)
|
||||
lanes |= 1 << (dssdev->phy.dsi.data2_lane - 1);
|
||||
if (dssdev->phy.dsi.data3_lane != 0)
|
||||
lanes |= 1 << (dssdev->phy.dsi.data3_lane - 1);
|
||||
if (dssdev->phy.dsi.data4_lane != 0)
|
||||
lanes |= 1 << (dssdev->phy.dsi.data4_lane - 1);
|
||||
for (i = 0; i < dsi->num_lanes_supported; ++i) {
|
||||
if (dsi->lanes[i].function != DSI_LANE_UNUSED)
|
||||
mask |= 1 << i;
|
||||
}
|
||||
|
||||
return lanes;
|
||||
return mask;
|
||||
}
|
||||
|
||||
static int dsi_cio_init(struct omap_dss_device *dssdev)
|
||||
|
@ -2385,7 +2392,6 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
|
|||
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
int r;
|
||||
int num_data_lanes_dssdev = dsi_get_num_data_lanes_dssdev(dssdev);
|
||||
u32 l;
|
||||
|
||||
DSSDBGF();
|
||||
|
@ -2407,7 +2413,9 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
|
|||
goto err_scp_clk_dom;
|
||||
}
|
||||
|
||||
dsi_set_lane_config(dssdev);
|
||||
r = dsi_set_lane_config(dssdev);
|
||||
if (r)
|
||||
goto err_scp_clk_dom;
|
||||
|
||||
/* set TX STOP MODE timer to maximum for this operation */
|
||||
l = dsi_read_reg(dsidev, DSI_TIMING1);
|
||||
|
@ -2418,7 +2426,8 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
|
|||
dsi_write_reg(dsidev, DSI_TIMING1, l);
|
||||
|
||||
if (dsi->ulps_enabled) {
|
||||
u32 lane_mask = DSI_CLK_P | DSI_DATA1_P | DSI_DATA2_P;
|
||||
unsigned mask_p;
|
||||
int i;
|
||||
|
||||
DSSDBG("manual ulps exit\n");
|
||||
|
||||
|
@ -2427,16 +2436,19 @@ static int dsi_cio_init(struct omap_dss_device *dssdev)
|
|||
* ULPS exit sequence, as after reset the DSS HW thinks
|
||||
* that we are not in ULPS mode, and refuses to send the
|
||||
* sequence. So we need to send the ULPS exit sequence
|
||||
* manually.
|
||||
* manually by setting positive lines high and negative lines
|
||||
* low for 1ms.
|
||||
*/
|
||||
|
||||
if (num_data_lanes_dssdev > 2)
|
||||
lane_mask |= DSI_DATA3_P;
|
||||
mask_p = 0;
|
||||
|
||||
if (num_data_lanes_dssdev > 3)
|
||||
lane_mask |= DSI_DATA4_P;
|
||||
for (i = 0; i < dsi->num_lanes_supported; ++i) {
|
||||
if (dsi->lanes[i].function == DSI_LANE_UNUSED)
|
||||
continue;
|
||||
mask_p |= 1 << i;
|
||||
}
|
||||
|
||||
dsi_cio_enable_lane_override(dssdev, lane_mask);
|
||||
dsi_cio_enable_lane_override(dssdev, mask_p, 0);
|
||||
}
|
||||
|
||||
r = dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ON);
|
||||
|
@ -2913,6 +2925,9 @@ static int dsi_vc_send_bta(struct platform_device *dsidev, int channel)
|
|||
|
||||
REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 6, 6); /* BTA_EN */
|
||||
|
||||
/* flush posted write */
|
||||
dsi_read_reg(dsidev, DSI_VC_CTRL(channel));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3513,7 +3528,8 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
|
|||
{
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
DECLARE_COMPLETION_ONSTACK(completion);
|
||||
int r;
|
||||
int r, i;
|
||||
unsigned mask;
|
||||
|
||||
DSSDBGF();
|
||||
|
||||
|
@ -3524,9 +3540,11 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
|
|||
if (dsi->ulps_enabled)
|
||||
return 0;
|
||||
|
||||
/* DDR_CLK_ALWAYS_ON */
|
||||
if (REG_GET(dsidev, DSI_CLK_CTRL, 13, 13)) {
|
||||
DSSERR("DDR_CLK_ALWAYS_ON enabled when entering ULPS\n");
|
||||
return -EIO;
|
||||
dsi_if_enable(dsidev, 0);
|
||||
REG_FLD_MOD(dsidev, DSI_CLK_CTRL, 0, 13, 13);
|
||||
dsi_if_enable(dsidev, 1);
|
||||
}
|
||||
|
||||
dsi_sync_vc(dsidev, 0);
|
||||
|
@ -3556,10 +3574,19 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
|
|||
if (r)
|
||||
return r;
|
||||
|
||||
mask = 0;
|
||||
|
||||
for (i = 0; i < dsi->num_lanes_supported; ++i) {
|
||||
if (dsi->lanes[i].function == DSI_LANE_UNUSED)
|
||||
continue;
|
||||
mask |= 1 << i;
|
||||
}
|
||||
/* Assert TxRequestEsc for data lanes and TxUlpsClk for clk lane */
|
||||
/* LANEx_ULPS_SIG2 */
|
||||
REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (1 << 0) | (1 << 1) | (1 << 2),
|
||||
7, 5);
|
||||
REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, mask, 9, 5);
|
||||
|
||||
/* flush posted write and wait for SCP interface to finish the write */
|
||||
dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG2);
|
||||
|
||||
if (wait_for_completion_timeout(&completion,
|
||||
msecs_to_jiffies(1000)) == 0) {
|
||||
|
@ -3572,8 +3599,10 @@ static int dsi_enter_ulps(struct platform_device *dsidev)
|
|||
DSI_CIO_IRQ_ULPSACTIVENOT_ALL0);
|
||||
|
||||
/* Reset LANEx_ULPS_SIG2 */
|
||||
REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, (0 << 0) | (0 << 1) | (0 << 2),
|
||||
7, 5);
|
||||
REG_FLD_MOD(dsidev, DSI_COMPLEXIO_CFG2, 0, 9, 5);
|
||||
|
||||
/* flush posted write and wait for SCP interface to finish the write */
|
||||
dsi_read_reg(dsidev, DSI_COMPLEXIO_CFG2);
|
||||
|
||||
dsi_cio_power(dsidev, DSI_COMPLEXIO_POWER_ULPS);
|
||||
|
||||
|
@ -3836,6 +3865,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev)
|
|||
static void dsi_proto_timings(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
unsigned tlpx, tclk_zero, tclk_prepare, tclk_trail;
|
||||
unsigned tclk_pre, tclk_post;
|
||||
unsigned ths_prepare, ths_prepare_ths_zero, ths_zero;
|
||||
|
@ -3843,7 +3873,7 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
|
|||
unsigned ddr_clk_pre, ddr_clk_post;
|
||||
unsigned enter_hs_mode_lat, exit_hs_mode_lat;
|
||||
unsigned ths_eot;
|
||||
int ndl = dsi_get_num_data_lanes_dssdev(dssdev);
|
||||
int ndl = dsi->num_lanes_used - 1;
|
||||
u32 r;
|
||||
|
||||
r = dsi_read_reg(dsidev, DSI_DSIPHY_CFG0);
|
||||
|
@ -3945,68 +3975,82 @@ static void dsi_proto_timings(struct omap_dss_device *dssdev)
|
|||
}
|
||||
}
|
||||
|
||||
int dsi_video_mode_enable(struct omap_dss_device *dssdev, int channel)
|
||||
int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel)
|
||||
{
|
||||
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
|
||||
int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt);
|
||||
u8 data_type;
|
||||
u16 word_count;
|
||||
int r;
|
||||
|
||||
switch (dssdev->panel.dsi_pix_fmt) {
|
||||
case OMAP_DSS_DSI_FMT_RGB888:
|
||||
data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24;
|
||||
break;
|
||||
case OMAP_DSS_DSI_FMT_RGB666:
|
||||
data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
|
||||
break;
|
||||
case OMAP_DSS_DSI_FMT_RGB666_PACKED:
|
||||
data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18;
|
||||
break;
|
||||
case OMAP_DSS_DSI_FMT_RGB565:
|
||||
data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
};
|
||||
if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
|
||||
switch (dssdev->panel.dsi_pix_fmt) {
|
||||
case OMAP_DSS_DSI_FMT_RGB888:
|
||||
data_type = MIPI_DSI_PACKED_PIXEL_STREAM_24;
|
||||
break;
|
||||
case OMAP_DSS_DSI_FMT_RGB666:
|
||||
data_type = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
|
||||
break;
|
||||
case OMAP_DSS_DSI_FMT_RGB666_PACKED:
|
||||
data_type = MIPI_DSI_PACKED_PIXEL_STREAM_18;
|
||||
break;
|
||||
case OMAP_DSS_DSI_FMT_RGB565:
|
||||
data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
};
|
||||
|
||||
dsi_if_enable(dsidev, false);
|
||||
dsi_vc_enable(dsidev, channel, false);
|
||||
dsi_if_enable(dsidev, false);
|
||||
dsi_vc_enable(dsidev, channel, false);
|
||||
|
||||
/* MODE, 1 = video mode */
|
||||
REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4);
|
||||
/* MODE, 1 = video mode */
|
||||
REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 1, 4, 4);
|
||||
|
||||
word_count = DIV_ROUND_UP(dssdev->panel.timings.x_res * bpp, 8);
|
||||
word_count = DIV_ROUND_UP(dssdev->panel.timings.x_res * bpp, 8);
|
||||
|
||||
dsi_vc_write_long_header(dsidev, channel, data_type, word_count, 0);
|
||||
dsi_vc_write_long_header(dsidev, channel, data_type,
|
||||
word_count, 0);
|
||||
|
||||
dsi_vc_enable(dsidev, channel, true);
|
||||
dsi_if_enable(dsidev, true);
|
||||
dsi_vc_enable(dsidev, channel, true);
|
||||
dsi_if_enable(dsidev, true);
|
||||
}
|
||||
|
||||
dssdev->manager->enable(dssdev->manager);
|
||||
r = dss_mgr_enable(dssdev->manager);
|
||||
if (r) {
|
||||
if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
|
||||
dsi_if_enable(dsidev, false);
|
||||
dsi_vc_enable(dsidev, channel, false);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(dsi_video_mode_enable);
|
||||
EXPORT_SYMBOL(dsi_enable_video_output);
|
||||
|
||||
void dsi_video_mode_disable(struct omap_dss_device *dssdev, int channel)
|
||||
void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel)
|
||||
{
|
||||
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
|
||||
|
||||
dsi_if_enable(dsidev, false);
|
||||
dsi_vc_enable(dsidev, channel, false);
|
||||
if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_VIDEO_MODE) {
|
||||
dsi_if_enable(dsidev, false);
|
||||
dsi_vc_enable(dsidev, channel, false);
|
||||
|
||||
/* MODE, 0 = command mode */
|
||||
REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 4, 4);
|
||||
/* MODE, 0 = command mode */
|
||||
REG_FLD_MOD(dsidev, DSI_VC_CTRL(channel), 0, 4, 4);
|
||||
|
||||
dsi_vc_enable(dsidev, channel, true);
|
||||
dsi_if_enable(dsidev, true);
|
||||
dsi_vc_enable(dsidev, channel, true);
|
||||
dsi_if_enable(dsidev, true);
|
||||
}
|
||||
|
||||
dssdev->manager->disable(dssdev->manager);
|
||||
dss_mgr_disable(dssdev->manager);
|
||||
}
|
||||
EXPORT_SYMBOL(dsi_video_mode_disable);
|
||||
EXPORT_SYMBOL(dsi_disable_video_output);
|
||||
|
||||
static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
|
||||
u16 x, u16 y, u16 w, u16 h)
|
||||
u16 w, u16 h)
|
||||
{
|
||||
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
|
@ -4021,8 +4065,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
|
|||
const unsigned channel = dsi->update_channel;
|
||||
const unsigned line_buf_size = dsi_get_line_buf_size(dsidev);
|
||||
|
||||
DSSDBG("dsi_update_screen_dispc(%d,%d %dx%d)\n",
|
||||
x, y, w, h);
|
||||
DSSDBG("dsi_update_screen_dispc(%dx%d)\n", w, h);
|
||||
|
||||
dsi_vc_config_source(dsidev, channel, DSI_VC_SOURCE_VP);
|
||||
|
||||
|
@ -4070,7 +4113,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev,
|
|||
msecs_to_jiffies(250));
|
||||
BUG_ON(r == 0);
|
||||
|
||||
dss_start_update(dssdev);
|
||||
dss_mgr_start_update(dssdev->manager);
|
||||
|
||||
if (dsi->te_enabled) {
|
||||
/* disable LP_RX_TO, so that we can receive TE. Time to wait
|
||||
|
@ -4146,66 +4189,27 @@ static void dsi_framedone_irq_callback(void *data, u32 mask)
|
|||
#endif
|
||||
}
|
||||
|
||||
int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
|
||||
u16 *x, u16 *y, u16 *w, u16 *h,
|
||||
bool enlarge_update_area)
|
||||
{
|
||||
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
|
||||
u16 dw, dh;
|
||||
|
||||
dssdev->driver->get_resolution(dssdev, &dw, &dh);
|
||||
|
||||
if (*x > dw || *y > dh)
|
||||
return -EINVAL;
|
||||
|
||||
if (*x + *w > dw)
|
||||
return -EINVAL;
|
||||
|
||||
if (*y + *h > dh)
|
||||
return -EINVAL;
|
||||
|
||||
if (*w == 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (*w == 0 || *h == 0)
|
||||
return -EINVAL;
|
||||
|
||||
dsi_perf_mark_setup(dsidev);
|
||||
|
||||
dss_setup_partial_planes(dssdev, x, y, w, h,
|
||||
enlarge_update_area);
|
||||
dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(omap_dsi_prepare_update);
|
||||
|
||||
int omap_dsi_update(struct omap_dss_device *dssdev,
|
||||
int channel,
|
||||
u16 x, u16 y, u16 w, u16 h,
|
||||
int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
|
||||
void (*callback)(int, void *), void *data)
|
||||
{
|
||||
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
u16 dw, dh;
|
||||
|
||||
dsi_perf_mark_setup(dsidev);
|
||||
|
||||
dsi->update_channel = channel;
|
||||
|
||||
/* OMAP DSS cannot send updates of odd widths.
|
||||
* omap_dsi_prepare_update() makes the widths even, but add a BUG_ON
|
||||
* here to make sure we catch erroneous updates. Otherwise we'll only
|
||||
* see rather obscure HW error happening, as DSS halts. */
|
||||
BUG_ON(x % 2 == 1);
|
||||
|
||||
dsi->framedone_callback = callback;
|
||||
dsi->framedone_data = data;
|
||||
|
||||
dsi->update_region.x = x;
|
||||
dsi->update_region.y = y;
|
||||
dsi->update_region.w = w;
|
||||
dsi->update_region.h = h;
|
||||
dsi->update_region.device = dssdev;
|
||||
dssdev->driver->get_resolution(dssdev, &dw, &dh);
|
||||
|
||||
dsi_update_screen_dispc(dssdev, x, y, w, h);
|
||||
#ifdef DEBUG
|
||||
dsi->update_bytes = dw * dh *
|
||||
dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) / 8;
|
||||
#endif
|
||||
dsi_update_screen_dispc(dssdev, dw, dh);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -4218,6 +4222,7 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
|
|||
int r;
|
||||
|
||||
if (dssdev->panel.dsi_mode == OMAP_DSS_DSI_CMD_MODE) {
|
||||
u16 dw, dh;
|
||||
u32 irq;
|
||||
struct omap_video_timings timings = {
|
||||
.hsw = 1,
|
||||
|
@ -4228,6 +4233,10 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev)
|
|||
.vbp = 0,
|
||||
};
|
||||
|
||||
dssdev->driver->get_resolution(dssdev, &dw, &dh);
|
||||
timings.x_res = dw;
|
||||
timings.y_res = dh;
|
||||
|
||||
irq = dssdev->manager->id == OMAP_DSS_CHANNEL_LCD ?
|
||||
DISPC_IRQ_FRAMEDONE : DISPC_IRQ_FRAMEDONE2;
|
||||
|
||||
|
@ -4330,6 +4339,12 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev)
|
|||
int dsi_module = dsi_get_dsidev_id(dsidev);
|
||||
int r;
|
||||
|
||||
r = dsi_parse_lane_config(dssdev);
|
||||
if (r) {
|
||||
DSSERR("illegal lane config");
|
||||
goto err0;
|
||||
}
|
||||
|
||||
r = dsi_pll_init(dsidev, true, true);
|
||||
if (r)
|
||||
goto err0;
|
||||
|
@ -4521,7 +4536,6 @@ int dsi_init_display(struct omap_dss_device *dssdev)
|
|||
{
|
||||
struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
|
||||
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
|
||||
int dsi_module = dsi_get_dsidev_id(dsidev);
|
||||
|
||||
DSSDBG("DSI init\n");
|
||||
|
||||
|
@ -4543,12 +4557,6 @@ int dsi_init_display(struct omap_dss_device *dssdev)
|
|||
dsi->vdds_dsi_reg = vdds_dsi;
|
||||
}
|
||||
|
||||
if (dsi_get_num_data_lanes_dssdev(dssdev) > dsi->num_data_lanes) {
|
||||
DSSERR("DSI%d can't support more than %d data lanes\n",
|
||||
dsi_module + 1, dsi->num_data_lanes);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -4771,7 +4779,13 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
|
|||
dev_dbg(&dsidev->dev, "OMAP DSI rev %d.%d\n",
|
||||
FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
|
||||
|
||||
dsi->num_data_lanes = dsi_get_num_data_lanes(dsidev);
|
||||
/* DSI on OMAP3 doesn't have register DSI_GNQ, set number
|
||||
* of data to 3 by default */
|
||||
if (dss_has_feature(FEAT_DSI_GNQ))
|
||||
/* NB_DATA_LANES */
|
||||
dsi->num_lanes_supported = 1 + REG_GET(dsidev, DSI_GNQ, 11, 9);
|
||||
else
|
||||
dsi->num_lanes_supported = 3;
|
||||
|
||||
dsi_runtime_put(dsidev);
|
||||
|
||||
|
|
|
@ -163,6 +163,34 @@ struct bus_type *dss_get_bus(void);
|
|||
struct regulator *dss_get_vdds_dsi(void);
|
||||
struct regulator *dss_get_vdds_sdi(void);
|
||||
|
||||
/* apply */
|
||||
void dss_apply_init(void);
|
||||
int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr);
|
||||
int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
|
||||
void dss_mgr_start_update(struct omap_overlay_manager *mgr);
|
||||
int omap_dss_mgr_apply(struct omap_overlay_manager *mgr);
|
||||
|
||||
int dss_mgr_enable(struct omap_overlay_manager *mgr);
|
||||
void dss_mgr_disable(struct omap_overlay_manager *mgr);
|
||||
int dss_mgr_set_info(struct omap_overlay_manager *mgr,
|
||||
struct omap_overlay_manager_info *info);
|
||||
void dss_mgr_get_info(struct omap_overlay_manager *mgr,
|
||||
struct omap_overlay_manager_info *info);
|
||||
int dss_mgr_set_device(struct omap_overlay_manager *mgr,
|
||||
struct omap_dss_device *dssdev);
|
||||
int dss_mgr_unset_device(struct omap_overlay_manager *mgr);
|
||||
|
||||
bool dss_ovl_is_enabled(struct omap_overlay *ovl);
|
||||
int dss_ovl_enable(struct omap_overlay *ovl);
|
||||
int dss_ovl_disable(struct omap_overlay *ovl);
|
||||
int dss_ovl_set_info(struct omap_overlay *ovl,
|
||||
struct omap_overlay_info *info);
|
||||
void dss_ovl_get_info(struct omap_overlay *ovl,
|
||||
struct omap_overlay_info *info);
|
||||
int dss_ovl_set_manager(struct omap_overlay *ovl,
|
||||
struct omap_overlay_manager *mgr);
|
||||
int dss_ovl_unset_manager(struct omap_overlay *ovl);
|
||||
|
||||
/* display */
|
||||
int dss_suspend_all_devices(void);
|
||||
int dss_resume_all_devices(void);
|
||||
|
@ -181,21 +209,22 @@ void default_get_overlay_fifo_thresholds(enum omap_plane plane,
|
|||
/* manager */
|
||||
int dss_init_overlay_managers(struct platform_device *pdev);
|
||||
void dss_uninit_overlay_managers(struct platform_device *pdev);
|
||||
int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
|
||||
void dss_setup_partial_planes(struct omap_dss_device *dssdev,
|
||||
u16 *x, u16 *y, u16 *w, u16 *h,
|
||||
bool enlarge_update_area);
|
||||
void dss_start_update(struct omap_dss_device *dssdev);
|
||||
int dss_mgr_simple_check(struct omap_overlay_manager *mgr,
|
||||
const struct omap_overlay_manager_info *info);
|
||||
int dss_mgr_check(struct omap_overlay_manager *mgr,
|
||||
struct omap_dss_device *dssdev,
|
||||
struct omap_overlay_manager_info *info,
|
||||
struct omap_overlay_info **overlay_infos);
|
||||
|
||||
/* overlay */
|
||||
void dss_init_overlays(struct platform_device *pdev);
|
||||
void dss_uninit_overlays(struct platform_device *pdev);
|
||||
int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev);
|
||||
void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr);
|
||||
#ifdef L4_EXAMPLE
|
||||
void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr);
|
||||
#endif
|
||||
void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
|
||||
int dss_ovl_simple_check(struct omap_overlay *ovl,
|
||||
const struct omap_overlay_info *info);
|
||||
int dss_ovl_check(struct omap_overlay *ovl,
|
||||
struct omap_overlay_info *info, struct omap_dss_device *dssdev);
|
||||
|
||||
/* DSS */
|
||||
int dss_init_platform_driver(void);
|
||||
|
@ -399,21 +428,22 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
|
|||
struct dispc_clock_info *cinfo);
|
||||
|
||||
|
||||
void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high);
|
||||
u32 dispc_ovl_get_fifo_size(enum omap_plane plane);
|
||||
u32 dispc_ovl_get_burst_size(enum omap_plane plane);
|
||||
int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi,
|
||||
bool ilace, enum omap_channel channel, bool replication,
|
||||
u32 fifo_low, u32 fifo_high);
|
||||
bool ilace, bool replication);
|
||||
int dispc_ovl_enable(enum omap_plane plane, bool enable);
|
||||
|
||||
void dispc_ovl_set_channel_out(enum omap_plane plane,
|
||||
enum omap_channel channel);
|
||||
|
||||
void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable);
|
||||
void dispc_mgr_set_lcd_size(enum omap_channel channel, u16 width, u16 height);
|
||||
void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable);
|
||||
void dispc_mgr_set_cpr_coef(enum omap_channel channel,
|
||||
struct omap_dss_cpr_coefs *coefs);
|
||||
u32 dispc_mgr_get_vsync_irq(enum omap_channel channel);
|
||||
u32 dispc_mgr_get_framedone_irq(enum omap_channel channel);
|
||||
bool dispc_mgr_go_busy(enum omap_channel channel);
|
||||
void dispc_mgr_go(enum omap_channel channel);
|
||||
bool dispc_mgr_is_enabled(enum omap_channel channel);
|
||||
void dispc_mgr_enable(enum omap_channel channel, bool enable);
|
||||
bool dispc_mgr_is_channel_enabled(enum omap_channel channel);
|
||||
void dispc_mgr_set_io_pad_mode(enum dss_io_pad_mode mode);
|
||||
|
@ -421,18 +451,6 @@ void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable);
|
|||
void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines);
|
||||
void dispc_mgr_set_lcd_display_type(enum omap_channel channel,
|
||||
enum omap_lcd_display_type type);
|
||||
void dispc_mgr_set_default_color(enum omap_channel channel, u32 color);
|
||||
u32 dispc_mgr_get_default_color(enum omap_channel channel);
|
||||
void dispc_mgr_set_trans_key(enum omap_channel ch,
|
||||
enum omap_dss_trans_key_type type,
|
||||
u32 trans_key);
|
||||
void dispc_mgr_get_trans_key(enum omap_channel ch,
|
||||
enum omap_dss_trans_key_type *type,
|
||||
u32 *trans_key);
|
||||
void dispc_mgr_enable_trans_key(enum omap_channel ch, bool enable);
|
||||
void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, bool enable);
|
||||
bool dispc_mgr_trans_key_enabled(enum omap_channel ch);
|
||||
bool dispc_mgr_alpha_fixed_zorder_enabled(enum omap_channel ch);
|
||||
void dispc_mgr_set_lcd_timings(enum omap_channel channel,
|
||||
struct omap_video_timings *timings);
|
||||
void dispc_mgr_set_pol_freq(enum omap_channel channel,
|
||||
|
@ -443,6 +461,8 @@ int dispc_mgr_set_clock_div(enum omap_channel channel,
|
|||
struct dispc_clock_info *cinfo);
|
||||
int dispc_mgr_get_clock_div(enum omap_channel channel,
|
||||
struct dispc_clock_info *cinfo);
|
||||
void dispc_mgr_setup(enum omap_channel channel,
|
||||
struct omap_overlay_manager_info *info);
|
||||
|
||||
/* VENC */
|
||||
#ifdef CONFIG_OMAP2_DSS_VENC
|
||||
|
|
|
@ -304,6 +304,11 @@ static const struct dss_param_range omap2_dss_param_range[] = {
|
|||
[FEAT_PARAM_DSIPLL_FINT] = { 0, 0 },
|
||||
[FEAT_PARAM_DSIPLL_LPDIV] = { 0, 0 },
|
||||
[FEAT_PARAM_DOWNSCALE] = { 1, 2 },
|
||||
/*
|
||||
* Assuming the line width buffer to be 768 pixels as OMAP2 DISPC
|
||||
* scaler cannot scale a image with width more than 768.
|
||||
*/
|
||||
[FEAT_PARAM_LINEWIDTH] = { 1, 768 },
|
||||
};
|
||||
|
||||
static const struct dss_param_range omap3_dss_param_range[] = {
|
||||
|
@ -316,6 +321,7 @@ static const struct dss_param_range omap3_dss_param_range[] = {
|
|||
[FEAT_PARAM_DSIPLL_FINT] = { 750000, 2100000 },
|
||||
[FEAT_PARAM_DSIPLL_LPDIV] = { 1, (1 << 13) - 1},
|
||||
[FEAT_PARAM_DOWNSCALE] = { 1, 4 },
|
||||
[FEAT_PARAM_LINEWIDTH] = { 1, 1024 },
|
||||
};
|
||||
|
||||
static const struct dss_param_range omap4_dss_param_range[] = {
|
||||
|
@ -328,6 +334,7 @@ static const struct dss_param_range omap4_dss_param_range[] = {
|
|||
[FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 },
|
||||
[FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 },
|
||||
[FEAT_PARAM_DOWNSCALE] = { 1, 4 },
|
||||
[FEAT_PARAM_LINEWIDTH] = { 1, 2048 },
|
||||
};
|
||||
|
||||
/* OMAP2 DSS Features */
|
||||
|
@ -465,6 +472,10 @@ static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
|
|||
.dump_core = ti_hdmi_4xxx_core_dump,
|
||||
.dump_pll = ti_hdmi_4xxx_pll_dump,
|
||||
.dump_phy = ti_hdmi_4xxx_phy_dump,
|
||||
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
|
||||
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
|
||||
.audio_enable = ti_hdmi_4xxx_wp_audio_enable,
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -86,6 +86,7 @@ enum dss_range_param {
|
|||
FEAT_PARAM_DSIPLL_FINT,
|
||||
FEAT_PARAM_DSIPLL_LPDIV,
|
||||
FEAT_PARAM_DOWNSCALE,
|
||||
FEAT_PARAM_LINEWIDTH,
|
||||
};
|
||||
|
||||
/* DSS Feature Functions */
|
||||
|
|
|
@ -333,7 +333,7 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
|
|||
if (r)
|
||||
return r;
|
||||
|
||||
dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 0);
|
||||
dss_mgr_disable(dssdev->manager);
|
||||
|
||||
p = &dssdev->panel.timings;
|
||||
|
||||
|
@ -387,9 +387,16 @@ static int hdmi_power_on(struct omap_dss_device *dssdev)
|
|||
|
||||
hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 1);
|
||||
|
||||
dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 1);
|
||||
r = dss_mgr_enable(dssdev->manager);
|
||||
if (r)
|
||||
goto err_mgr_enable;
|
||||
|
||||
return 0;
|
||||
|
||||
err_mgr_enable:
|
||||
hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0);
|
||||
hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
|
||||
hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
|
||||
err:
|
||||
hdmi_runtime_put();
|
||||
return -EIO;
|
||||
|
@ -397,7 +404,7 @@ err:
|
|||
|
||||
static void hdmi_power_off(struct omap_dss_device *dssdev)
|
||||
{
|
||||
dispc_mgr_enable(OMAP_DSS_CHANNEL_DIGIT, 0);
|
||||
dss_mgr_disable(dssdev->manager);
|
||||
|
||||
hdmi.ip_data.ops->video_enable(&hdmi.ip_data, 0);
|
||||
hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
|
||||
|
@ -554,11 +561,44 @@ void omapdss_hdmi_display_disable(struct omap_dss_device *dssdev)
|
|||
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
|
||||
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
|
||||
|
||||
static int hdmi_audio_hw_params(struct hdmi_ip_data *ip_data,
|
||||
struct snd_pcm_substream *substream,
|
||||
static int hdmi_audio_trigger(struct snd_pcm_substream *substream, int cmd,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
struct platform_device *pdev = to_platform_device(codec->dev);
|
||||
struct hdmi_ip_data *ip_data = snd_soc_codec_get_drvdata(codec);
|
||||
int err = 0;
|
||||
|
||||
if (!(ip_data->ops) && !(ip_data->ops->audio_enable)) {
|
||||
dev_err(&pdev->dev, "Cannot enable/disable audio\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
ip_data->ops->audio_enable(ip_data, true);
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
ip_data->ops->audio_enable(ip_data, false);
|
||||
break;
|
||||
default:
|
||||
err = -EINVAL;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int hdmi_audio_hw_params(struct snd_pcm_substream *substream,
|
||||
struct snd_pcm_hw_params *params,
|
||||
struct snd_soc_dai *dai)
|
||||
{
|
||||
struct snd_soc_pcm_runtime *rtd = substream->private_data;
|
||||
struct snd_soc_codec *codec = rtd->codec;
|
||||
struct hdmi_ip_data *ip_data = snd_soc_codec_get_drvdata(codec);
|
||||
struct hdmi_audio_format audio_format;
|
||||
struct hdmi_audio_dma audio_dma;
|
||||
struct hdmi_core_audio_config core_cfg;
|
||||
|
@ -698,7 +738,16 @@ static int hdmi_audio_startup(struct snd_pcm_substream *substream,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int hdmi_audio_codec_probe(struct snd_soc_codec *codec)
|
||||
{
|
||||
struct hdmi_ip_data *priv = &hdmi.ip_data;
|
||||
|
||||
snd_soc_codec_set_drvdata(codec, priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct snd_soc_codec_driver hdmi_audio_codec_drv = {
|
||||
.probe = hdmi_audio_codec_probe,
|
||||
};
|
||||
|
||||
static struct snd_soc_dai_ops hdmi_audio_codec_ops = {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -38,7 +38,7 @@
|
|||
#include "dss_features.h"
|
||||
|
||||
static int num_overlays;
|
||||
static struct list_head overlay_list;
|
||||
static struct omap_overlay *overlays;
|
||||
|
||||
static ssize_t overlay_name_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
|
@ -124,19 +124,31 @@ err:
|
|||
|
||||
static ssize_t overlay_input_size_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d\n",
|
||||
ovl->info.width, ovl->info.height);
|
||||
info.width, info.height);
|
||||
}
|
||||
|
||||
static ssize_t overlay_screen_width_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.screen_width);
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width);
|
||||
}
|
||||
|
||||
static ssize_t overlay_position_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d\n",
|
||||
ovl->info.pos_x, ovl->info.pos_y);
|
||||
info.pos_x, info.pos_y);
|
||||
}
|
||||
|
||||
static ssize_t overlay_position_store(struct omap_overlay *ovl,
|
||||
|
@ -170,8 +182,12 @@ static ssize_t overlay_position_store(struct omap_overlay *ovl,
|
|||
|
||||
static ssize_t overlay_output_size_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d,%d\n",
|
||||
ovl->info.out_width, ovl->info.out_height);
|
||||
info.out_width, info.out_height);
|
||||
}
|
||||
|
||||
static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
|
||||
|
@ -205,7 +221,7 @@ static ssize_t overlay_output_size_store(struct omap_overlay *ovl,
|
|||
|
||||
static ssize_t overlay_enabled_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.enabled);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl));
|
||||
}
|
||||
|
||||
static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
|
||||
|
@ -213,33 +229,30 @@ static ssize_t overlay_enabled_store(struct omap_overlay *ovl, const char *buf,
|
|||
{
|
||||
int r;
|
||||
bool enable;
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
r = strtobool(buf, &enable);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
info.enabled = enable;
|
||||
if (enable)
|
||||
r = ovl->enable(ovl);
|
||||
else
|
||||
r = ovl->disable(ovl);
|
||||
|
||||
r = ovl->set_overlay_info(ovl, &info);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (ovl->manager) {
|
||||
r = ovl->manager->apply(ovl->manager);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ssize_t overlay_global_alpha_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
ovl->info.global_alpha);
|
||||
info.global_alpha);
|
||||
}
|
||||
|
||||
static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
|
||||
|
@ -276,8 +289,12 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
|
|||
static ssize_t overlay_pre_mult_alpha_show(struct omap_overlay *ovl,
|
||||
char *buf)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
ovl->info.pre_mult_alpha);
|
||||
info.pre_mult_alpha);
|
||||
}
|
||||
|
||||
static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
|
||||
|
@ -313,7 +330,11 @@ static ssize_t overlay_pre_mult_alpha_store(struct omap_overlay *ovl,
|
|||
|
||||
static ssize_t overlay_zorder_show(struct omap_overlay *ovl, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", ovl->info.zorder);
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder);
|
||||
}
|
||||
|
||||
static ssize_t overlay_zorder_store(struct omap_overlay *ovl,
|
||||
|
@ -430,183 +451,6 @@ static struct kobj_type overlay_ktype = {
|
|||
.default_attrs = overlay_sysfs_attrs,
|
||||
};
|
||||
|
||||
/* Check if overlay parameters are compatible with display */
|
||||
int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct omap_overlay_info *info;
|
||||
u16 outw, outh;
|
||||
u16 dw, dh;
|
||||
int i;
|
||||
|
||||
if (!dssdev)
|
||||
return 0;
|
||||
|
||||
if (!ovl->info.enabled)
|
||||
return 0;
|
||||
|
||||
info = &ovl->info;
|
||||
|
||||
if (info->paddr == 0) {
|
||||
DSSDBG("check_overlay failed: paddr 0\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dssdev->driver->get_resolution(dssdev, &dw, &dh);
|
||||
|
||||
DSSDBG("check_overlay %d: (%d,%d %dx%d -> %dx%d) disp (%dx%d)\n",
|
||||
ovl->id,
|
||||
info->pos_x, info->pos_y,
|
||||
info->width, info->height,
|
||||
info->out_width, info->out_height,
|
||||
dw, dh);
|
||||
|
||||
if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
|
||||
outw = info->width;
|
||||
outh = info->height;
|
||||
} else {
|
||||
if (info->out_width == 0)
|
||||
outw = info->width;
|
||||
else
|
||||
outw = info->out_width;
|
||||
|
||||
if (info->out_height == 0)
|
||||
outh = info->height;
|
||||
else
|
||||
outh = info->out_height;
|
||||
}
|
||||
|
||||
if (dw < info->pos_x + outw) {
|
||||
DSSDBG("check_overlay failed 1: %d < %d + %d\n",
|
||||
dw, info->pos_x, outw);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dh < info->pos_y + outh) {
|
||||
DSSDBG("check_overlay failed 2: %d < %d + %d\n",
|
||||
dh, info->pos_y, outh);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((ovl->supported_modes & info->color_mode) == 0) {
|
||||
DSSERR("overlay doesn't support mode %d\n", info->color_mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) {
|
||||
if (info->zorder < 0 || info->zorder > 3) {
|
||||
DSSERR("zorder out of range: %d\n",
|
||||
info->zorder);
|
||||
return -EINVAL;
|
||||
}
|
||||
/*
|
||||
* Check that zorder doesn't match with zorder of any other
|
||||
* overlay which is enabled and is also connected to the same
|
||||
* manager
|
||||
*/
|
||||
for (i = 0; i < omap_dss_get_num_overlays(); i++) {
|
||||
struct omap_overlay *tmp_ovl = omap_dss_get_overlay(i);
|
||||
|
||||
if (tmp_ovl->id != ovl->id &&
|
||||
tmp_ovl->manager == ovl->manager &&
|
||||
tmp_ovl->info.enabled == true &&
|
||||
tmp_ovl->info.zorder == info->zorder) {
|
||||
DSSERR("%s and %s have same zorder: %d\n",
|
||||
ovl->name, tmp_ovl->name, info->zorder);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dss_ovl_set_overlay_info(struct omap_overlay *ovl,
|
||||
struct omap_overlay_info *info)
|
||||
{
|
||||
int r;
|
||||
struct omap_overlay_info old_info;
|
||||
|
||||
old_info = ovl->info;
|
||||
ovl->info = *info;
|
||||
|
||||
if (ovl->manager) {
|
||||
r = dss_check_overlay(ovl, ovl->manager->device);
|
||||
if (r) {
|
||||
ovl->info = old_info;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
ovl->info_dirty = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dss_ovl_get_overlay_info(struct omap_overlay *ovl,
|
||||
struct omap_overlay_info *info)
|
||||
{
|
||||
*info = ovl->info;
|
||||
}
|
||||
|
||||
static int dss_ovl_wait_for_go(struct omap_overlay *ovl)
|
||||
{
|
||||
return dss_mgr_wait_for_go_ovl(ovl);
|
||||
}
|
||||
|
||||
static int omap_dss_set_manager(struct omap_overlay *ovl,
|
||||
struct omap_overlay_manager *mgr)
|
||||
{
|
||||
if (!mgr)
|
||||
return -EINVAL;
|
||||
|
||||
if (ovl->manager) {
|
||||
DSSERR("overlay '%s' already has a manager '%s'\n",
|
||||
ovl->name, ovl->manager->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ovl->info.enabled) {
|
||||
DSSERR("overlay has to be disabled to change the manager\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ovl->manager = mgr;
|
||||
ovl->manager_changed = true;
|
||||
|
||||
/* XXX: When there is an overlay on a DSI manual update display, and
|
||||
* the overlay is first disabled, then moved to tv, and enabled, we
|
||||
* seem to get SYNC_LOST_DIGIT error.
|
||||
*
|
||||
* Waiting doesn't seem to help, but updating the manual update display
|
||||
* after disabling the overlay seems to fix this. This hints that the
|
||||
* overlay is perhaps somehow tied to the LCD output until the output
|
||||
* is updated.
|
||||
*
|
||||
* Userspace workaround for this is to update the LCD after disabling
|
||||
* the overlay, but before moving the overlay to TV.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int omap_dss_unset_manager(struct omap_overlay *ovl)
|
||||
{
|
||||
if (!ovl->manager) {
|
||||
DSSERR("failed to detach overlay: manager not set\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ovl->info.enabled) {
|
||||
DSSERR("overlay has to be disabled to unset the manager\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ovl->manager = NULL;
|
||||
ovl->manager_changed = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int omap_dss_get_num_overlays(void)
|
||||
{
|
||||
return num_overlays;
|
||||
|
@ -615,134 +459,65 @@ EXPORT_SYMBOL(omap_dss_get_num_overlays);
|
|||
|
||||
struct omap_overlay *omap_dss_get_overlay(int num)
|
||||
{
|
||||
int i = 0;
|
||||
struct omap_overlay *ovl;
|
||||
if (num >= num_overlays)
|
||||
return NULL;
|
||||
|
||||
list_for_each_entry(ovl, &overlay_list, list) {
|
||||
if (i++ == num)
|
||||
return ovl;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return &overlays[num];
|
||||
}
|
||||
EXPORT_SYMBOL(omap_dss_get_overlay);
|
||||
|
||||
static void omap_dss_add_overlay(struct omap_overlay *overlay)
|
||||
{
|
||||
++num_overlays;
|
||||
list_add_tail(&overlay->list, &overlay_list);
|
||||
}
|
||||
|
||||
static struct omap_overlay *dispc_overlays[MAX_DSS_OVERLAYS];
|
||||
|
||||
void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr)
|
||||
{
|
||||
mgr->num_overlays = dss_feat_get_num_ovls();
|
||||
mgr->overlays = dispc_overlays;
|
||||
}
|
||||
|
||||
#ifdef L4_EXAMPLE
|
||||
static struct omap_overlay *l4_overlays[1];
|
||||
void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr)
|
||||
{
|
||||
mgr->num_overlays = 1;
|
||||
mgr->overlays = l4_overlays;
|
||||
}
|
||||
#endif
|
||||
|
||||
void dss_init_overlays(struct platform_device *pdev)
|
||||
{
|
||||
int i, r;
|
||||
|
||||
INIT_LIST_HEAD(&overlay_list);
|
||||
num_overlays = dss_feat_get_num_ovls();
|
||||
|
||||
num_overlays = 0;
|
||||
overlays = kzalloc(sizeof(struct omap_overlay) * num_overlays,
|
||||
GFP_KERNEL);
|
||||
|
||||
for (i = 0; i < dss_feat_get_num_ovls(); ++i) {
|
||||
struct omap_overlay *ovl;
|
||||
ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
|
||||
BUG_ON(overlays == NULL);
|
||||
|
||||
BUG_ON(ovl == NULL);
|
||||
for (i = 0; i < num_overlays; ++i) {
|
||||
struct omap_overlay *ovl = &overlays[i];
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
ovl->name = "gfx";
|
||||
ovl->id = OMAP_DSS_GFX;
|
||||
ovl->info.global_alpha = 255;
|
||||
ovl->info.zorder = 0;
|
||||
break;
|
||||
case 1:
|
||||
ovl->name = "vid1";
|
||||
ovl->id = OMAP_DSS_VIDEO1;
|
||||
ovl->info.global_alpha = 255;
|
||||
ovl->info.zorder =
|
||||
dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0;
|
||||
break;
|
||||
case 2:
|
||||
ovl->name = "vid2";
|
||||
ovl->id = OMAP_DSS_VIDEO2;
|
||||
ovl->info.global_alpha = 255;
|
||||
ovl->info.zorder =
|
||||
dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0;
|
||||
break;
|
||||
case 3:
|
||||
ovl->name = "vid3";
|
||||
ovl->id = OMAP_DSS_VIDEO3;
|
||||
ovl->info.global_alpha = 255;
|
||||
ovl->info.zorder =
|
||||
dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
ovl->set_manager = &omap_dss_set_manager;
|
||||
ovl->unset_manager = &omap_dss_unset_manager;
|
||||
ovl->set_overlay_info = &dss_ovl_set_overlay_info;
|
||||
ovl->get_overlay_info = &dss_ovl_get_overlay_info;
|
||||
ovl->wait_for_go = &dss_ovl_wait_for_go;
|
||||
ovl->is_enabled = &dss_ovl_is_enabled;
|
||||
ovl->enable = &dss_ovl_enable;
|
||||
ovl->disable = &dss_ovl_disable;
|
||||
ovl->set_manager = &dss_ovl_set_manager;
|
||||
ovl->unset_manager = &dss_ovl_unset_manager;
|
||||
ovl->set_overlay_info = &dss_ovl_set_info;
|
||||
ovl->get_overlay_info = &dss_ovl_get_info;
|
||||
ovl->wait_for_go = &dss_mgr_wait_for_go_ovl;
|
||||
|
||||
ovl->caps = dss_feat_get_overlay_caps(ovl->id);
|
||||
ovl->supported_modes =
|
||||
dss_feat_get_supported_color_modes(ovl->id);
|
||||
|
||||
omap_dss_add_overlay(ovl);
|
||||
|
||||
r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
|
||||
&pdev->dev.kobj, "overlay%d", i);
|
||||
|
||||
if (r) {
|
||||
DSSERR("failed to create sysfs file\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
dispc_overlays[i] = ovl;
|
||||
}
|
||||
|
||||
#ifdef L4_EXAMPLE
|
||||
{
|
||||
struct omap_overlay *ovl;
|
||||
ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
|
||||
|
||||
BUG_ON(ovl == NULL);
|
||||
|
||||
ovl->name = "l4";
|
||||
ovl->supported_modes = OMAP_DSS_COLOR_RGB24U;
|
||||
|
||||
ovl->set_manager = &omap_dss_set_manager;
|
||||
ovl->unset_manager = &omap_dss_unset_manager;
|
||||
ovl->set_overlay_info = &dss_ovl_set_overlay_info;
|
||||
ovl->get_overlay_info = &dss_ovl_get_overlay_info;
|
||||
|
||||
omap_dss_add_overlay(ovl);
|
||||
|
||||
r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
|
||||
&pdev->dev.kobj, "overlayl4");
|
||||
|
||||
if (r)
|
||||
DSSERR("failed to create sysfs file\n");
|
||||
|
||||
l4_overlays[0] = ovl;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* connect overlays to the new device, if not already connected. if force
|
||||
|
@ -795,8 +570,8 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
|
|||
ovl = omap_dss_get_overlay(i);
|
||||
if (!ovl->manager || force) {
|
||||
if (ovl->manager)
|
||||
omap_dss_unset_manager(ovl);
|
||||
omap_dss_set_manager(ovl, mgr);
|
||||
ovl->unset_manager(ovl);
|
||||
ovl->set_manager(ovl, mgr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -806,17 +581,95 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
|
|||
|
||||
void dss_uninit_overlays(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_overlay *ovl;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_overlays; ++i) {
|
||||
struct omap_overlay *ovl = &overlays[i];
|
||||
|
||||
while (!list_empty(&overlay_list)) {
|
||||
ovl = list_first_entry(&overlay_list,
|
||||
struct omap_overlay, list);
|
||||
list_del(&ovl->list);
|
||||
kobject_del(&ovl->kobj);
|
||||
kobject_put(&ovl->kobj);
|
||||
kfree(ovl);
|
||||
}
|
||||
|
||||
kfree(overlays);
|
||||
overlays = NULL;
|
||||
num_overlays = 0;
|
||||
}
|
||||
|
||||
int dss_ovl_simple_check(struct omap_overlay *ovl,
|
||||
const struct omap_overlay_info *info)
|
||||
{
|
||||
if (info->paddr == 0) {
|
||||
DSSERR("check_overlay: paddr cannot be 0\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
|
||||
if (info->out_width != 0 && info->width != info->out_width) {
|
||||
DSSERR("check_overlay: overlay %d doesn't support "
|
||||
"scaling\n", ovl->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (info->out_height != 0 && info->height != info->out_height) {
|
||||
DSSERR("check_overlay: overlay %d doesn't support "
|
||||
"scaling\n", ovl->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ovl->supported_modes & info->color_mode) == 0) {
|
||||
DSSERR("check_overlay: overlay %d doesn't support mode %d\n",
|
||||
ovl->id, info->color_mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (info->zorder >= omap_dss_get_num_overlays()) {
|
||||
DSSERR("check_overlay: zorder %d too high\n", info->zorder);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dss_ovl_check(struct omap_overlay *ovl,
|
||||
struct omap_overlay_info *info, struct omap_dss_device *dssdev)
|
||||
{
|
||||
u16 outw, outh;
|
||||
u16 dw, dh;
|
||||
|
||||
if (dssdev == NULL)
|
||||
return 0;
|
||||
|
||||
dssdev->driver->get_resolution(dssdev, &dw, &dh);
|
||||
|
||||
if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
|
||||
outw = info->width;
|
||||
outh = info->height;
|
||||
} else {
|
||||
if (info->out_width == 0)
|
||||
outw = info->width;
|
||||
else
|
||||
outw = info->out_width;
|
||||
|
||||
if (info->out_height == 0)
|
||||
outh = info->height;
|
||||
else
|
||||
outh = info->out_height;
|
||||
}
|
||||
|
||||
if (dw < info->pos_x + outw) {
|
||||
DSSERR("overlay %d horizontally not inside the display area "
|
||||
"(%d + %d >= %d)\n",
|
||||
ovl->id, info->pos_x, outw, dw);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dh < info->pos_y + outh) {
|
||||
DSSERR("overlay %d vertically not inside the display area "
|
||||
"(%d + %d >= %d)\n",
|
||||
ovl->id, info->pos_y, outh, dh);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -784,7 +784,6 @@ int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
|
|||
if (*w == 0 || *h == 0)
|
||||
return -EINVAL;
|
||||
|
||||
dss_setup_partial_planes(dssdev, x, y, w, h, true);
|
||||
dispc_mgr_set_lcd_size(dssdev->manager->id, *w, *h);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -123,10 +123,14 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
|
|||
goto err_sdi_enable;
|
||||
mdelay(2);
|
||||
|
||||
dssdev->manager->enable(dssdev->manager);
|
||||
r = dss_mgr_enable(dssdev->manager);
|
||||
if (r)
|
||||
goto err_mgr_enable;
|
||||
|
||||
return 0;
|
||||
|
||||
err_mgr_enable:
|
||||
dss_sdi_disable();
|
||||
err_sdi_enable:
|
||||
err_set_dispc_clock_div:
|
||||
err_set_dss_clock_div:
|
||||
|
@ -145,7 +149,7 @@ EXPORT_SYMBOL(omapdss_sdi_display_enable);
|
|||
|
||||
void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
dssdev->manager->disable(dssdev->manager);
|
||||
dss_mgr_disable(dssdev->manager);
|
||||
|
||||
dss_sdi_disable();
|
||||
|
||||
|
|
|
@ -110,6 +110,11 @@ struct ti_hdmi_ip_ops {
|
|||
|
||||
void (*dump_phy)(struct hdmi_ip_data *ip_data, struct seq_file *s);
|
||||
|
||||
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
|
||||
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
|
||||
void (*audio_enable)(struct hdmi_ip_data *ip_data, bool start);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
struct hdmi_ip_data {
|
||||
|
@ -134,5 +139,8 @@ void ti_hdmi_4xxx_wp_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
|
|||
void ti_hdmi_4xxx_pll_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
|
||||
void ti_hdmi_4xxx_core_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
|
||||
void ti_hdmi_4xxx_phy_dump(struct hdmi_ip_data *ip_data, struct seq_file *s);
|
||||
|
||||
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
|
||||
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
|
||||
void ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data, bool enable);
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -1204,36 +1204,13 @@ int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int hdmi_audio_trigger(struct hdmi_ip_data *ip_data,
|
||||
struct snd_pcm_substream *substream, int cmd,
|
||||
struct snd_soc_dai *dai)
|
||||
void ti_hdmi_4xxx_wp_audio_enable(struct hdmi_ip_data *ip_data, bool enable)
|
||||
{
|
||||
int err = 0;
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
|
||||
REG_FLD_MOD(hdmi_av_base(ip_data),
|
||||
HDMI_CORE_AV_AUD_MODE, 1, 0, 0);
|
||||
REG_FLD_MOD(hdmi_wp_base(ip_data),
|
||||
HDMI_WP_AUDIO_CTRL, 1, 31, 31);
|
||||
REG_FLD_MOD(hdmi_wp_base(ip_data),
|
||||
HDMI_WP_AUDIO_CTRL, 1, 30, 30);
|
||||
break;
|
||||
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
REG_FLD_MOD(hdmi_av_base(ip_data),
|
||||
HDMI_CORE_AV_AUD_MODE, 0, 0, 0);
|
||||
REG_FLD_MOD(hdmi_wp_base(ip_data),
|
||||
HDMI_WP_AUDIO_CTRL, 0, 30, 30);
|
||||
REG_FLD_MOD(hdmi_wp_base(ip_data),
|
||||
HDMI_WP_AUDIO_CTRL, 0, 31, 31);
|
||||
break;
|
||||
default:
|
||||
err = -EINVAL;
|
||||
}
|
||||
return err;
|
||||
REG_FLD_MOD(hdmi_av_base(ip_data),
|
||||
HDMI_CORE_AV_AUD_MODE, enable, 0, 0);
|
||||
REG_FLD_MOD(hdmi_wp_base(ip_data),
|
||||
HDMI_WP_AUDIO_CTRL, enable, 31, 31);
|
||||
REG_FLD_MOD(hdmi_wp_base(ip_data),
|
||||
HDMI_WP_AUDIO_CTRL, enable, 30, 30);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -576,9 +576,6 @@ struct hdmi_core_audio_config {
|
|||
|
||||
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
|
||||
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
|
||||
int hdmi_audio_trigger(struct hdmi_ip_data *ip_data,
|
||||
struct snd_pcm_substream *substream, int cmd,
|
||||
struct snd_soc_dai *dai);
|
||||
int hdmi_config_audio_acr(struct hdmi_ip_data *ip_data,
|
||||
u32 sample_freq, u32 *n, u32 *cts);
|
||||
void hdmi_core_audio_infoframe_config(struct hdmi_ip_data *ip_data,
|
||||
|
|
|
@ -417,9 +417,10 @@ static const struct venc_config *venc_timings_to_config(
|
|||
BUG();
|
||||
}
|
||||
|
||||
static void venc_power_on(struct omap_dss_device *dssdev)
|
||||
static int venc_power_on(struct omap_dss_device *dssdev)
|
||||
{
|
||||
u32 l;
|
||||
int r;
|
||||
|
||||
venc_reset();
|
||||
venc_write_config(venc_timings_to_config(&dssdev->panel.timings));
|
||||
|
@ -447,7 +448,22 @@ static void venc_power_on(struct omap_dss_device *dssdev)
|
|||
if (dssdev->platform_enable)
|
||||
dssdev->platform_enable(dssdev);
|
||||
|
||||
dssdev->manager->enable(dssdev->manager);
|
||||
r = dss_mgr_enable(dssdev->manager);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
venc_write_reg(VENC_OUTPUT_CONTROL, 0);
|
||||
dss_set_dac_pwrdn_bgz(0);
|
||||
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
|
||||
regulator_disable(venc.vdda_dac_reg);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void venc_power_off(struct omap_dss_device *dssdev)
|
||||
|
@ -455,7 +471,7 @@ static void venc_power_off(struct omap_dss_device *dssdev)
|
|||
venc_write_reg(VENC_OUTPUT_CONTROL, 0);
|
||||
dss_set_dac_pwrdn_bgz(0);
|
||||
|
||||
dssdev->manager->disable(dssdev->manager);
|
||||
dss_mgr_disable(dssdev->manager);
|
||||
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
|
@ -504,7 +520,9 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
|
|||
if (r)
|
||||
goto err1;
|
||||
|
||||
venc_power_on(dssdev);
|
||||
r = venc_power_on(dssdev);
|
||||
if (r)
|
||||
goto err2;
|
||||
|
||||
venc.wss_data = 0;
|
||||
|
||||
|
@ -512,6 +530,8 @@ static int venc_panel_enable(struct omap_dss_device *dssdev)
|
|||
|
||||
mutex_unlock(&venc.venc_lock);
|
||||
return 0;
|
||||
err2:
|
||||
venc_runtime_put();
|
||||
err1:
|
||||
omap_dss_stop_device(dssdev);
|
||||
err0:
|
||||
|
|
|
@ -111,28 +111,22 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
|
|||
set_fb_fix(fbi);
|
||||
}
|
||||
|
||||
if (pi->enabled) {
|
||||
struct omap_overlay_info info;
|
||||
if (!pi->enabled) {
|
||||
r = ovl->disable(ovl);
|
||||
if (r)
|
||||
goto undo;
|
||||
}
|
||||
|
||||
if (pi->enabled) {
|
||||
r = omapfb_setup_overlay(fbi, ovl, pi->pos_x, pi->pos_y,
|
||||
pi->out_width, pi->out_height);
|
||||
if (r)
|
||||
goto undo;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
if (!info.enabled) {
|
||||
info.enabled = pi->enabled;
|
||||
r = ovl->set_overlay_info(ovl, &info);
|
||||
if (r)
|
||||
goto undo;
|
||||
}
|
||||
} else {
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
|
||||
info.enabled = pi->enabled;
|
||||
info.pos_x = pi->pos_x;
|
||||
info.pos_y = pi->pos_y;
|
||||
info.out_width = pi->out_width;
|
||||
|
@ -146,6 +140,12 @@ static int omapfb_setup_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
|
|||
if (ovl->manager)
|
||||
ovl->manager->apply(ovl->manager);
|
||||
|
||||
if (pi->enabled) {
|
||||
r = ovl->enable(ovl);
|
||||
if (r)
|
||||
goto undo;
|
||||
}
|
||||
|
||||
/* Release the locks in a specific order to keep lockdep happy */
|
||||
if (old_rg->id > new_rg->id) {
|
||||
omapfb_put_mem_region(old_rg);
|
||||
|
@ -189,19 +189,19 @@ static int omapfb_query_plane(struct fb_info *fbi, struct omapfb_plane_info *pi)
|
|||
memset(pi, 0, sizeof(*pi));
|
||||
} else {
|
||||
struct omap_overlay *ovl;
|
||||
struct omap_overlay_info *ovli;
|
||||
struct omap_overlay_info ovli;
|
||||
|
||||
ovl = ofbi->overlays[0];
|
||||
ovli = &ovl->info;
|
||||
ovl->get_overlay_info(ovl, &ovli);
|
||||
|
||||
pi->pos_x = ovli->pos_x;
|
||||
pi->pos_y = ovli->pos_y;
|
||||
pi->enabled = ovli->enabled;
|
||||
pi->pos_x = ovli.pos_x;
|
||||
pi->pos_y = ovli.pos_y;
|
||||
pi->enabled = ovl->is_enabled(ovl);
|
||||
pi->channel_out = 0; /* xxx */
|
||||
pi->mirror = 0;
|
||||
pi->mem_idx = get_mem_idx(ofbi);
|
||||
pi->out_width = ovli->out_width;
|
||||
pi->out_height = ovli->out_height;
|
||||
pi->out_width = ovli.out_width;
|
||||
pi->out_height = ovli.out_height;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -238,7 +238,9 @@ static int omapfb_setup_mem(struct fb_info *fbi, struct omapfb_mem_info *mi)
|
|||
continue;
|
||||
|
||||
for (j = 0; j < ofbi2->num_overlays; j++) {
|
||||
if (ofbi2->overlays[j]->info.enabled) {
|
||||
struct omap_overlay *ovl;
|
||||
ovl = ofbi2->overlays[j];
|
||||
if (ovl->is_enabled(ovl)) {
|
||||
r = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
@ -970,16 +970,20 @@ int omapfb_apply_changes(struct fb_info *fbi, int init)
|
|||
outh = var->yres;
|
||||
}
|
||||
} else {
|
||||
outw = ovl->info.out_width;
|
||||
outh = ovl->info.out_height;
|
||||
struct omap_overlay_info info;
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
outw = info.out_width;
|
||||
outh = info.out_height;
|
||||
}
|
||||
|
||||
if (init) {
|
||||
posx = 0;
|
||||
posy = 0;
|
||||
} else {
|
||||
posx = ovl->info.pos_x;
|
||||
posy = ovl->info.pos_y;
|
||||
struct omap_overlay_info info;
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
posx = info.pos_x;
|
||||
posy = info.pos_y;
|
||||
}
|
||||
|
||||
r = omapfb_setup_overlay(fbi, ovl, posx, posy, outw, outh);
|
||||
|
@ -2067,6 +2071,8 @@ static int omapfb_create_framebuffers(struct omapfb2_device *fbdev)
|
|||
if (ofbi->num_overlays > 0) {
|
||||
struct omap_overlay *ovl = ofbi->overlays[0];
|
||||
|
||||
ovl->manager->apply(ovl->manager);
|
||||
|
||||
r = omapfb_overlay_enable(ovl, 1);
|
||||
|
||||
if (r) {
|
||||
|
|
|
@ -473,7 +473,9 @@ static ssize_t store_size(struct device *dev, struct device_attribute *attr,
|
|||
continue;
|
||||
|
||||
for (j = 0; j < ofbi2->num_overlays; j++) {
|
||||
if (ofbi2->overlays[j]->info.enabled) {
|
||||
struct omap_overlay *ovl;
|
||||
ovl = ofbi2->overlays[j];
|
||||
if (ovl->is_enabled(ovl)) {
|
||||
r = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
@ -181,13 +181,10 @@ static inline void omapfb_unlock(struct omapfb2_device *fbdev)
|
|||
static inline int omapfb_overlay_enable(struct omap_overlay *ovl,
|
||||
int enable)
|
||||
{
|
||||
struct omap_overlay_info info;
|
||||
|
||||
ovl->get_overlay_info(ovl, &info);
|
||||
if (info.enabled == enable)
|
||||
return 0;
|
||||
info.enabled = enable;
|
||||
return ovl->set_overlay_info(ovl, &info);
|
||||
if (enable)
|
||||
return ovl->enable(ovl);
|
||||
else
|
||||
return ovl->disable(ovl);
|
||||
}
|
||||
|
||||
static inline struct omapfb2_mem_region *
|
||||
|
|
|
@ -193,17 +193,6 @@ static struct platform_driver rgbfb_driver = {
|
|||
.remove = rgbfb_remove,
|
||||
};
|
||||
|
||||
static int __init rgbfb_init(void)
|
||||
{
|
||||
return platform_driver_register(&rgbfb_driver);
|
||||
}
|
||||
|
||||
static void __exit rgbfb_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&rgbfb_driver);
|
||||
}
|
||||
|
||||
module_init(rgbfb_init);
|
||||
module_exit(rgbfb_exit);
|
||||
module_platform_driver(rgbfb_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -856,17 +856,6 @@ static struct platform_driver sdum_driver = {
|
|||
.resume = sdum_resume,
|
||||
};
|
||||
|
||||
int __init sdum_init(void)
|
||||
{
|
||||
return platform_driver_register(&sdum_driver);
|
||||
}
|
||||
|
||||
static void __exit sdum_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&sdum_driver);
|
||||
};
|
||||
|
||||
module_init(sdum_init);
|
||||
module_exit(sdum_exit);
|
||||
module_platform_driver(sdum_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -832,17 +832,7 @@ static struct platform_driver pxa168fb_driver = {
|
|||
.remove = __devexit_p(pxa168fb_remove),
|
||||
};
|
||||
|
||||
static int __init pxa168fb_init(void)
|
||||
{
|
||||
return platform_driver_register(&pxa168fb_driver);
|
||||
}
|
||||
module_init(pxa168fb_init);
|
||||
|
||||
static void __exit pxa168fb_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&pxa168fb_driver);
|
||||
}
|
||||
module_exit(pxa168fb_exit);
|
||||
module_platform_driver(pxa168fb_driver);
|
||||
|
||||
MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com> "
|
||||
"Green Wan <gwan@marvell.com>");
|
||||
|
|
|
@ -747,20 +747,7 @@ static struct platform_driver pxa3xx_gcu_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init
|
||||
pxa3xx_gcu_init(void)
|
||||
{
|
||||
return platform_driver_register(&pxa3xx_gcu_driver);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
pxa3xx_gcu_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&pxa3xx_gcu_driver);
|
||||
}
|
||||
|
||||
module_init(pxa3xx_gcu_init);
|
||||
module_exit(pxa3xx_gcu_exit);
|
||||
module_platform_driver(pxa3xx_gcu_driver);
|
||||
|
||||
MODULE_DESCRIPTION("PXA3xx graphics controller unit driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -192,6 +192,7 @@ struct s3c_fb_vsync {
|
|||
* @regs: The mapped hardware registers.
|
||||
* @variant: Variant information for this hardware.
|
||||
* @enabled: A bitmask of enabled hardware windows.
|
||||
* @output_on: Flag if the physical output is enabled.
|
||||
* @pdata: The platform configuration data passed with the device.
|
||||
* @windows: The hardware windows that have been claimed.
|
||||
* @irq_no: IRQ line number
|
||||
|
@ -208,6 +209,7 @@ struct s3c_fb {
|
|||
struct s3c_fb_variant variant;
|
||||
|
||||
unsigned char enabled;
|
||||
bool output_on;
|
||||
|
||||
struct s3c_fb_platdata *pdata;
|
||||
struct s3c_fb_win *windows[S3C_FB_MAX_WIN];
|
||||
|
@ -440,6 +442,39 @@ static void shadow_protect_win(struct s3c_fb_win *win, bool protect)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* s3c_fb_enable() - Set the state of the main LCD output
|
||||
* @sfb: The main framebuffer state.
|
||||
* @enable: The state to set.
|
||||
*/
|
||||
static void s3c_fb_enable(struct s3c_fb *sfb, int enable)
|
||||
{
|
||||
u32 vidcon0 = readl(sfb->regs + VIDCON0);
|
||||
|
||||
if (enable && !sfb->output_on)
|
||||
pm_runtime_get_sync(sfb->dev);
|
||||
|
||||
if (enable) {
|
||||
vidcon0 |= VIDCON0_ENVID | VIDCON0_ENVID_F;
|
||||
} else {
|
||||
/* see the note in the framebuffer datasheet about
|
||||
* why you cannot take both of these bits down at the
|
||||
* same time. */
|
||||
|
||||
if (vidcon0 & VIDCON0_ENVID) {
|
||||
vidcon0 |= VIDCON0_ENVID;
|
||||
vidcon0 &= ~VIDCON0_ENVID_F;
|
||||
}
|
||||
}
|
||||
|
||||
writel(vidcon0, sfb->regs + VIDCON0);
|
||||
|
||||
if (!enable && sfb->output_on)
|
||||
pm_runtime_put_sync(sfb->dev);
|
||||
|
||||
sfb->output_on = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* s3c_fb_set_par() - framebuffer request to set new framebuffer state.
|
||||
* @info: The framebuffer to change.
|
||||
|
@ -461,6 +496,8 @@ static int s3c_fb_set_par(struct fb_info *info)
|
|||
|
||||
dev_dbg(sfb->dev, "setting framebuffer parameters\n");
|
||||
|
||||
pm_runtime_get_sync(sfb->dev);
|
||||
|
||||
shadow_protect_win(win, 1);
|
||||
|
||||
switch (var->bits_per_pixel) {
|
||||
|
@ -510,9 +547,10 @@ static int s3c_fb_set_par(struct fb_info *info)
|
|||
if (sfb->variant.is_2443)
|
||||
data |= (1 << 5);
|
||||
|
||||
data |= VIDCON0_ENVID | VIDCON0_ENVID_F;
|
||||
writel(data, regs + VIDCON0);
|
||||
|
||||
s3c_fb_enable(sfb, 1);
|
||||
|
||||
data = VIDTCON0_VBPD(var->upper_margin - 1) |
|
||||
VIDTCON0_VFPD(var->lower_margin - 1) |
|
||||
VIDTCON0_VSPW(var->vsync_len - 1);
|
||||
|
@ -574,6 +612,7 @@ static int s3c_fb_set_par(struct fb_info *info)
|
|||
}
|
||||
|
||||
data = WINCONx_ENWIN;
|
||||
sfb->enabled |= (1 << win->index);
|
||||
|
||||
/* note, since we have to round up the bits-per-pixel, we end up
|
||||
* relying on the bitfield information for r/g/b/a to work out
|
||||
|
@ -621,7 +660,8 @@ static int s3c_fb_set_par(struct fb_info *info)
|
|||
} else if (var->transp.length == 1)
|
||||
data |= WINCON1_BPPMODE_25BPP_A1888
|
||||
| WINCON1_BLD_PIX;
|
||||
else if (var->transp.length == 4)
|
||||
else if ((var->transp.length == 4) ||
|
||||
(var->transp.length == 8))
|
||||
data |= WINCON1_BPPMODE_28BPP_A4888
|
||||
| WINCON1_BLD_PIX | WINCON1_ALPHA_SEL;
|
||||
else
|
||||
|
@ -654,6 +694,8 @@ static int s3c_fb_set_par(struct fb_info *info)
|
|||
|
||||
shadow_protect_win(win, 0);
|
||||
|
||||
pm_runtime_put_sync(sfb->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -725,6 +767,8 @@ static int s3c_fb_setcolreg(unsigned regno,
|
|||
dev_dbg(sfb->dev, "%s: win %d: %d => rgb=%d/%d/%d\n",
|
||||
__func__, win->index, regno, red, green, blue);
|
||||
|
||||
pm_runtime_get_sync(sfb->dev);
|
||||
|
||||
switch (info->fix.visual) {
|
||||
case FB_VISUAL_TRUECOLOR:
|
||||
/* true-colour, use pseudo-palette */
|
||||
|
@ -752,38 +796,14 @@ static int s3c_fb_setcolreg(unsigned regno,
|
|||
break;
|
||||
|
||||
default:
|
||||
pm_runtime_put_sync(sfb->dev);
|
||||
return 1; /* unknown type */
|
||||
}
|
||||
|
||||
pm_runtime_put_sync(sfb->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* s3c_fb_enable() - Set the state of the main LCD output
|
||||
* @sfb: The main framebuffer state.
|
||||
* @enable: The state to set.
|
||||
*/
|
||||
static void s3c_fb_enable(struct s3c_fb *sfb, int enable)
|
||||
{
|
||||
u32 vidcon0 = readl(sfb->regs + VIDCON0);
|
||||
|
||||
if (enable)
|
||||
vidcon0 |= VIDCON0_ENVID | VIDCON0_ENVID_F;
|
||||
else {
|
||||
/* see the note in the framebuffer datasheet about
|
||||
* why you cannot take both of these bits down at the
|
||||
* same time. */
|
||||
|
||||
if (!(vidcon0 & VIDCON0_ENVID))
|
||||
return;
|
||||
|
||||
vidcon0 |= VIDCON0_ENVID;
|
||||
vidcon0 &= ~VIDCON0_ENVID_F;
|
||||
}
|
||||
|
||||
writel(vidcon0, sfb->regs + VIDCON0);
|
||||
}
|
||||
|
||||
/**
|
||||
* s3c_fb_blank() - blank or unblank the given window
|
||||
* @blank_mode: The blank state from FB_BLANK_*
|
||||
|
@ -800,6 +820,8 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info)
|
|||
|
||||
dev_dbg(sfb->dev, "blank mode %d\n", blank_mode);
|
||||
|
||||
pm_runtime_get_sync(sfb->dev);
|
||||
|
||||
wincon = readl(sfb->regs + sfb->variant.wincon + (index * 4));
|
||||
|
||||
switch (blank_mode) {
|
||||
|
@ -810,12 +832,16 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info)
|
|||
|
||||
case FB_BLANK_NORMAL:
|
||||
/* disable the DMA and display 0x0 (black) */
|
||||
shadow_protect_win(win, 1);
|
||||
writel(WINxMAP_MAP | WINxMAP_MAP_COLOUR(0x0),
|
||||
sfb->regs + sfb->variant.winmap + (index * 4));
|
||||
shadow_protect_win(win, 0);
|
||||
break;
|
||||
|
||||
case FB_BLANK_UNBLANK:
|
||||
shadow_protect_win(win, 1);
|
||||
writel(0x0, sfb->regs + sfb->variant.winmap + (index * 4));
|
||||
shadow_protect_win(win, 0);
|
||||
wincon |= WINCONx_ENWIN;
|
||||
sfb->enabled |= (1 << index);
|
||||
break;
|
||||
|
@ -823,10 +849,13 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info)
|
|||
case FB_BLANK_VSYNC_SUSPEND:
|
||||
case FB_BLANK_HSYNC_SUSPEND:
|
||||
default:
|
||||
pm_runtime_put_sync(sfb->dev);
|
||||
return 1;
|
||||
}
|
||||
|
||||
shadow_protect_win(win, 1);
|
||||
writel(wincon, sfb->regs + sfb->variant.wincon + (index * 4));
|
||||
shadow_protect_win(win, 0);
|
||||
|
||||
/* Check the enabled state to see if we need to be running the
|
||||
* main LCD interface, as if there are no active windows then
|
||||
|
@ -845,8 +874,13 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info)
|
|||
/* we're stuck with this until we can do something about overriding
|
||||
* the power control using the blanking event for a single fb.
|
||||
*/
|
||||
if (index == sfb->pdata->default_win)
|
||||
if (index == sfb->pdata->default_win) {
|
||||
shadow_protect_win(win, 1);
|
||||
s3c_fb_enable(sfb, blank_mode != FB_BLANK_POWERDOWN ? 1 : 0);
|
||||
shadow_protect_win(win, 0);
|
||||
}
|
||||
|
||||
pm_runtime_put_sync(sfb->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -870,6 +904,8 @@ static int s3c_fb_pan_display(struct fb_var_screeninfo *var,
|
|||
void __iomem *buf = sfb->regs + win->index * 8;
|
||||
unsigned int start_boff, end_boff;
|
||||
|
||||
pm_runtime_get_sync(sfb->dev);
|
||||
|
||||
/* Offset in bytes to the start of the displayed area */
|
||||
start_boff = var->yoffset * info->fix.line_length;
|
||||
/* X offset depends on the current bpp */
|
||||
|
@ -888,6 +924,7 @@ static int s3c_fb_pan_display(struct fb_var_screeninfo *var,
|
|||
break;
|
||||
default:
|
||||
dev_err(sfb->dev, "invalid bpp\n");
|
||||
pm_runtime_put_sync(sfb->dev);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
@ -903,6 +940,7 @@ static int s3c_fb_pan_display(struct fb_var_screeninfo *var,
|
|||
|
||||
shadow_protect_win(win, 0);
|
||||
|
||||
pm_runtime_put_sync(sfb->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -992,11 +1030,16 @@ static int s3c_fb_wait_for_vsync(struct s3c_fb *sfb, u32 crtc)
|
|||
if (crtc != 0)
|
||||
return -ENODEV;
|
||||
|
||||
pm_runtime_get_sync(sfb->dev);
|
||||
|
||||
count = sfb->vsync_info.count;
|
||||
s3c_fb_enable_irq(sfb);
|
||||
ret = wait_event_interruptible_timeout(sfb->vsync_info.wait,
|
||||
count != sfb->vsync_info.count,
|
||||
msecs_to_jiffies(VSYNC_TIMEOUT_MSEC));
|
||||
|
||||
pm_runtime_put_sync(sfb->dev);
|
||||
|
||||
if (ret == 0)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
|
@ -1027,30 +1070,8 @@ static int s3c_fb_ioctl(struct fb_info *info, unsigned int cmd,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int s3c_fb_open(struct fb_info *info, int user)
|
||||
{
|
||||
struct s3c_fb_win *win = info->par;
|
||||
struct s3c_fb *sfb = win->parent;
|
||||
|
||||
pm_runtime_get_sync(sfb->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int s3c_fb_release(struct fb_info *info, int user)
|
||||
{
|
||||
struct s3c_fb_win *win = info->par;
|
||||
struct s3c_fb *sfb = win->parent;
|
||||
|
||||
pm_runtime_put_sync(sfb->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct fb_ops s3c_fb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.fb_open = s3c_fb_open,
|
||||
.fb_release = s3c_fb_release,
|
||||
.fb_check_var = s3c_fb_check_var,
|
||||
.fb_set_par = s3c_fb_set_par,
|
||||
.fb_blank = s3c_fb_blank,
|
||||
|
@ -1452,7 +1473,7 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
|
|||
dev_err(dev, "failed to create window %d\n", win);
|
||||
for (; win >= 0; win--)
|
||||
s3c_fb_release_win(sfb, sfb->windows[win]);
|
||||
goto err_irq;
|
||||
goto err_pm_runtime;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1461,7 +1482,8 @@ static int __devinit s3c_fb_probe(struct platform_device *pdev)
|
|||
|
||||
return 0;
|
||||
|
||||
err_irq:
|
||||
err_pm_runtime:
|
||||
pm_runtime_put_sync(sfb->dev);
|
||||
free_irq(sfb->irq_no, sfb);
|
||||
|
||||
err_ioremap:
|
||||
|
@ -1471,6 +1493,8 @@ err_req_region:
|
|||
release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res));
|
||||
|
||||
err_lcd_clk:
|
||||
pm_runtime_disable(sfb->dev);
|
||||
|
||||
if (!sfb->variant.has_clksel) {
|
||||
clk_disable(sfb->lcd_clk);
|
||||
clk_put(sfb->lcd_clk);
|
||||
|
@ -1524,7 +1548,7 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int s3c_fb_suspend(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
|
@ -1571,10 +1595,15 @@ static int s3c_fb_resume(struct device *dev)
|
|||
|
||||
for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) {
|
||||
void __iomem *regs = sfb->regs + sfb->variant.keycon;
|
||||
win = sfb->windows[win_no];
|
||||
if (!win)
|
||||
continue;
|
||||
|
||||
shadow_protect_win(win, 1);
|
||||
regs += (win_no * 8);
|
||||
writel(0xffffff, regs + WKEYCON0);
|
||||
writel(0xffffff, regs + WKEYCON1);
|
||||
shadow_protect_win(win, 0);
|
||||
}
|
||||
|
||||
/* restore framebuffers */
|
||||
|
@ -1589,27 +1618,19 @@ static int s3c_fb_resume(struct device *dev)
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_RUNTIME
|
||||
static int s3c_fb_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct s3c_fb *sfb = platform_get_drvdata(pdev);
|
||||
struct s3c_fb_win *win;
|
||||
int win_no;
|
||||
|
||||
for (win_no = S3C_FB_MAX_WIN - 1; win_no >= 0; win_no--) {
|
||||
win = sfb->windows[win_no];
|
||||
if (!win)
|
||||
continue;
|
||||
|
||||
/* use the blank function to push into power-down */
|
||||
s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
|
||||
}
|
||||
|
||||
if (!sfb->variant.has_clksel)
|
||||
clk_disable(sfb->lcd_clk);
|
||||
|
||||
clk_disable(sfb->bus_clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1618,8 +1639,6 @@ static int s3c_fb_runtime_resume(struct device *dev)
|
|||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct s3c_fb *sfb = platform_get_drvdata(pdev);
|
||||
struct s3c_fb_platdata *pd = sfb->pdata;
|
||||
struct s3c_fb_win *win;
|
||||
int win_no;
|
||||
|
||||
clk_enable(sfb->bus_clk);
|
||||
|
||||
|
@ -1630,39 +1649,10 @@ static int s3c_fb_runtime_resume(struct device *dev)
|
|||
pd->setup_gpio();
|
||||
writel(pd->vidcon1, sfb->regs + VIDCON1);
|
||||
|
||||
/* zero all windows before we do anything */
|
||||
for (win_no = 0; win_no < sfb->variant.nr_windows; win_no++)
|
||||
s3c_fb_clear_win(sfb, win_no);
|
||||
|
||||
for (win_no = 0; win_no < sfb->variant.nr_windows - 1; win_no++) {
|
||||
void __iomem *regs = sfb->regs + sfb->variant.keycon;
|
||||
|
||||
regs += (win_no * 8);
|
||||
writel(0xffffff, regs + WKEYCON0);
|
||||
writel(0xffffff, regs + WKEYCON1);
|
||||
}
|
||||
|
||||
/* restore framebuffers */
|
||||
for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) {
|
||||
win = sfb->windows[win_no];
|
||||
if (!win)
|
||||
continue;
|
||||
|
||||
dev_dbg(&pdev->dev, "resuming window %d\n", win_no);
|
||||
s3c_fb_set_par(win->fbinfo);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
#define s3c_fb_suspend NULL
|
||||
#define s3c_fb_resume NULL
|
||||
#define s3c_fb_runtime_suspend NULL
|
||||
#define s3c_fb_runtime_resume NULL
|
||||
#endif
|
||||
|
||||
|
||||
#define VALID_BPP124 (VALID_BPP(1) | VALID_BPP(2) | VALID_BPP(4))
|
||||
#define VALID_BPP1248 (VALID_BPP124 | VALID_BPP(8))
|
||||
|
||||
|
@ -1985,10 +1975,9 @@ static struct platform_device_id s3c_fb_driver_ids[] = {
|
|||
MODULE_DEVICE_TABLE(platform, s3c_fb_driver_ids);
|
||||
|
||||
static const struct dev_pm_ops s3cfb_pm_ops = {
|
||||
.suspend = s3c_fb_suspend,
|
||||
.resume = s3c_fb_resume,
|
||||
.runtime_suspend = s3c_fb_runtime_suspend,
|
||||
.runtime_resume = s3c_fb_runtime_resume,
|
||||
SET_SYSTEM_SLEEP_PM_OPS(s3c_fb_suspend, s3c_fb_resume)
|
||||
SET_RUNTIME_PM_OPS(s3c_fb_runtime_suspend, s3c_fb_runtime_resume,
|
||||
NULL)
|
||||
};
|
||||
|
||||
static struct platform_driver s3c_fb_driver = {
|
||||
|
@ -2002,18 +1991,7 @@ static struct platform_driver s3c_fb_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init s3c_fb_init(void)
|
||||
{
|
||||
return platform_driver_register(&s3c_fb_driver);
|
||||
}
|
||||
|
||||
static void __exit s3c_fb_cleanup(void)
|
||||
{
|
||||
platform_driver_unregister(&s3c_fb_driver);
|
||||
}
|
||||
|
||||
module_init(s3c_fb_init);
|
||||
module_exit(s3c_fb_cleanup);
|
||||
module_platform_driver(s3c_fb_driver);
|
||||
|
||||
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
|
||||
MODULE_DESCRIPTION("Samsung S3C SoC Framebuffer driver");
|
||||
|
|
|
@ -26,8 +26,8 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/div64.h>
|
||||
|
||||
#include <asm/mach/map.h>
|
||||
|
@ -45,10 +45,10 @@
|
|||
#ifdef CONFIG_FB_S3C2410_DEBUG
|
||||
static int debug = 1;
|
||||
#else
|
||||
static int debug = 0;
|
||||
static int debug;
|
||||
#endif
|
||||
|
||||
#define dprintk(msg...) if (debug) { printk(KERN_DEBUG "s3c2410fb: " msg); }
|
||||
#define dprintk(msg...) if (debug) printk(KERN_DEBUG "s3c2410fb: " msg);
|
||||
|
||||
/* useful functions */
|
||||
|
||||
|
@ -567,11 +567,10 @@ static int s3c2410fb_blank(int blank_mode, struct fb_info *info)
|
|||
|
||||
tpal_reg += is_s3c2412(fbi) ? S3C2412_TPAL : S3C2410_TPAL;
|
||||
|
||||
if (blank_mode == FB_BLANK_POWERDOWN) {
|
||||
if (blank_mode == FB_BLANK_POWERDOWN)
|
||||
s3c2410fb_lcd_enable(fbi, 0);
|
||||
} else {
|
||||
else
|
||||
s3c2410fb_lcd_enable(fbi, 1);
|
||||
}
|
||||
|
||||
if (blank_mode == FB_BLANK_UNBLANK)
|
||||
writel(0x0, tpal_reg);
|
||||
|
@ -812,7 +811,7 @@ static inline void s3c2410fb_cpufreq_deregister(struct s3c2410fb_info *info)
|
|||
#endif
|
||||
|
||||
|
||||
static char driver_name[] = "s3c2410fb";
|
||||
static const char driver_name[] = "s3c2410fb";
|
||||
|
||||
static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
|
||||
enum s3c_drv_type drv_type)
|
||||
|
@ -881,7 +880,10 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
|
|||
goto release_mem;
|
||||
}
|
||||
|
||||
info->irq_base = info->io + ((drv_type == DRV_S3C2412) ? S3C2412_LCDINTBASE : S3C2410_LCDINTBASE);
|
||||
if (drv_type == DRV_S3C2412)
|
||||
info->irq_base = info->io + S3C2412_LCDINTBASE;
|
||||
else
|
||||
info->irq_base = info->io + S3C2410_LCDINTBASE;
|
||||
|
||||
dprintk("devinit\n");
|
||||
|
||||
|
@ -927,7 +929,7 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
|
|||
clk_enable(info->clk);
|
||||
dprintk("got and enabled clock\n");
|
||||
|
||||
msleep(1);
|
||||
usleep_range(1000, 1000);
|
||||
|
||||
info->clk_rate = clk_get_rate(info->clk);
|
||||
|
||||
|
@ -975,9 +977,8 @@ static int __devinit s3c24xxfb_probe(struct platform_device *pdev,
|
|||
|
||||
/* create device files */
|
||||
ret = device_create_file(&pdev->dev, &dev_attr_debug);
|
||||
if (ret) {
|
||||
if (ret)
|
||||
printk(KERN_ERR "failed to add debug attribute\n");
|
||||
}
|
||||
|
||||
printk(KERN_INFO "fb%d: %s frame buffer device\n",
|
||||
fbinfo->node, fbinfo->fix.id);
|
||||
|
@ -1027,7 +1028,7 @@ static int __devexit s3c2410fb_remove(struct platform_device *pdev)
|
|||
s3c2410fb_cpufreq_deregister(info);
|
||||
|
||||
s3c2410fb_lcd_enable(info, 0);
|
||||
msleep(1);
|
||||
usleep_range(1000, 1000);
|
||||
|
||||
s3c2410fb_unmap_video_memory(fbinfo);
|
||||
|
||||
|
@ -1064,7 +1065,7 @@ static int s3c2410fb_suspend(struct platform_device *dev, pm_message_t state)
|
|||
* the LCD DMA engine is not going to get back on the bus
|
||||
* before the clock goes off again (bjd) */
|
||||
|
||||
msleep(1);
|
||||
usleep_range(1000, 1000);
|
||||
clk_disable(info->clk);
|
||||
|
||||
return 0;
|
||||
|
@ -1076,7 +1077,7 @@ static int s3c2410fb_resume(struct platform_device *dev)
|
|||
struct s3c2410fb_info *info = fbinfo->par;
|
||||
|
||||
clk_enable(info->clk);
|
||||
msleep(1);
|
||||
usleep_range(1000, 1000);
|
||||
|
||||
s3c2410fb_init_registers(fbinfo);
|
||||
|
||||
|
|
|
@ -727,7 +727,7 @@ static int s3fb_set_par(struct fb_info *info)
|
|||
if (par->chip == CHIP_988_VIRGE_VX) {
|
||||
vga_wcrt(par->state.vgabase, 0x50, 0x00);
|
||||
vga_wcrt(par->state.vgabase, 0x67, 0x50);
|
||||
|
||||
msleep(10); /* screen remains blank sometimes without this */
|
||||
vga_wcrt(par->state.vgabase, 0x63, (mode <= 2) ? 0x90 : 0x09);
|
||||
vga_wcrt(par->state.vgabase, 0x66, 0x90);
|
||||
}
|
||||
|
@ -901,7 +901,8 @@ static int s3fb_set_par(struct fb_info *info)
|
|||
|
||||
/* Set Data Transfer Position */
|
||||
hsstart = ((info->var.xres + info->var.right_margin) * hmul) / 8;
|
||||
value = clamp((htotal + hsstart + 1) / 2, hsstart + 4, htotal + 1);
|
||||
/* + 2 is needed for Virge/VX, does no harm on other cards */
|
||||
value = clamp((htotal + hsstart + 1) / 2 + 2, hsstart + 4, htotal + 1);
|
||||
svga_wcrt_multi(par->state.vgabase, s3_dtpc_regs, value);
|
||||
|
||||
memset_io(info->screen_base, 0x00, screen_size);
|
||||
|
@ -1216,6 +1217,31 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i
|
|||
info->screen_size = 2 << 20;
|
||||
break;
|
||||
}
|
||||
} else if (par->chip == CHIP_988_VIRGE_VX) {
|
||||
switch ((regval & 0x60) >> 5) {
|
||||
case 0: /* 2MB */
|
||||
info->screen_size = 2 << 20;
|
||||
break;
|
||||
case 1: /* 4MB */
|
||||
info->screen_size = 4 << 20;
|
||||
break;
|
||||
case 2: /* 6MB */
|
||||
info->screen_size = 6 << 20;
|
||||
break;
|
||||
case 3: /* 8MB */
|
||||
info->screen_size = 8 << 20;
|
||||
break;
|
||||
}
|
||||
/* off-screen memory */
|
||||
regval = vga_rcrt(par->state.vgabase, 0x37);
|
||||
switch ((regval & 0x60) >> 5) {
|
||||
case 1: /* 4MB */
|
||||
info->screen_size -= 4 << 20;
|
||||
break;
|
||||
case 2: /* 2MB */
|
||||
info->screen_size -= 2 << 20;
|
||||
break;
|
||||
}
|
||||
} else
|
||||
info->screen_size = s3_memsizes[regval >> 5] << 10;
|
||||
info->fix.smem_len = info->screen_size;
|
||||
|
|
|
@ -76,7 +76,7 @@ int sbusfb_mmap_helper(struct sbus_mmap_map *map,
|
|||
map_offset = (physbase + map[i].poff) & POFF_MASK;
|
||||
break;
|
||||
}
|
||||
if (!map_size){
|
||||
if (!map_size) {
|
||||
page += PAGE_SIZE;
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -585,18 +585,7 @@ static struct platform_driver sh7760_lcdc_driver = {
|
|||
.remove = __devexit_p(sh7760fb_remove),
|
||||
};
|
||||
|
||||
static int __init sh7760fb_init(void)
|
||||
{
|
||||
return platform_driver_register(&sh7760_lcdc_driver);
|
||||
}
|
||||
|
||||
static void __exit sh7760fb_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&sh7760_lcdc_driver);
|
||||
}
|
||||
|
||||
module_init(sh7760fb_init);
|
||||
module_exit(sh7760fb_exit);
|
||||
module_platform_driver(sh7760_lcdc_driver);
|
||||
|
||||
MODULE_AUTHOR("Nobuhiro Iwamatsu, Manuel Lauss");
|
||||
MODULE_DESCRIPTION("FBdev for SH7760/63 integrated LCD Controller");
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -41,6 +42,7 @@
|
|||
#define VMCTR1 0x0020
|
||||
#define VMCTR2 0x0024
|
||||
#define VMLEN1 0x0028
|
||||
#define VMLEN2 0x002c
|
||||
#define CMTSRTREQ 0x0070
|
||||
#define CMTSRTCTR 0x00d0
|
||||
|
||||
|
@ -51,8 +53,7 @@ struct sh_mipi {
|
|||
void __iomem *base;
|
||||
void __iomem *linkbase;
|
||||
struct clk *dsit_clk;
|
||||
struct clk *dsip_clk;
|
||||
struct device *dev;
|
||||
struct platform_device *pdev;
|
||||
|
||||
void *next_board_data;
|
||||
void (*next_display_on)(void *board_data, struct fb_info *info);
|
||||
|
@ -124,35 +125,15 @@ static void sh_mipi_shutdown(struct platform_device *pdev)
|
|||
sh_mipi_dsi_enable(mipi, false);
|
||||
}
|
||||
|
||||
static void mipi_display_on(void *arg, struct fb_info *info)
|
||||
{
|
||||
struct sh_mipi *mipi = arg;
|
||||
|
||||
pm_runtime_get_sync(mipi->dev);
|
||||
sh_mipi_dsi_enable(mipi, true);
|
||||
|
||||
if (mipi->next_display_on)
|
||||
mipi->next_display_on(mipi->next_board_data, info);
|
||||
}
|
||||
|
||||
static void mipi_display_off(void *arg)
|
||||
{
|
||||
struct sh_mipi *mipi = arg;
|
||||
|
||||
if (mipi->next_display_off)
|
||||
mipi->next_display_off(mipi->next_board_data);
|
||||
|
||||
sh_mipi_dsi_enable(mipi, false);
|
||||
pm_runtime_put(mipi->dev);
|
||||
}
|
||||
|
||||
static int __init sh_mipi_setup(struct sh_mipi *mipi,
|
||||
struct sh_mipi_dsi_info *pdata)
|
||||
{
|
||||
void __iomem *base = mipi->base;
|
||||
struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan;
|
||||
u32 pctype, datatype, pixfmt, linelength, vmctr2 = 0x00e00000;
|
||||
u32 pctype, datatype, pixfmt, linelength, vmctr2;
|
||||
u32 tmp, top, bottom, delay, div;
|
||||
bool yuv;
|
||||
int bpp;
|
||||
|
||||
/*
|
||||
* Select data format. MIPI DSI is not hot-pluggable, so, we just use
|
||||
|
@ -253,6 +234,9 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
|
|||
(!yuv && ch->interface_type != RGB24))
|
||||
return -EINVAL;
|
||||
|
||||
if (!pdata->lane)
|
||||
return -EINVAL;
|
||||
|
||||
/* reset DSI link */
|
||||
iowrite32(0x00000001, base + SYSCTRL);
|
||||
/* Hold reset for 100 cycles of the slowest of bus, HS byte and LP clock */
|
||||
|
@ -261,15 +245,6 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
|
|||
|
||||
/* setup DSI link */
|
||||
|
||||
/*
|
||||
* Default = ULPS enable |
|
||||
* Contention detection enabled |
|
||||
* EoT packet transmission enable |
|
||||
* CRC check enable |
|
||||
* ECC check enable
|
||||
* additionally enable first two lanes
|
||||
*/
|
||||
iowrite32(0x00003703, base + SYSCONF);
|
||||
/*
|
||||
* T_wakeup = 0x7000
|
||||
* T_hs-trail = 3
|
||||
|
@ -290,15 +265,24 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
|
|||
iowrite32(0x0fffffff, base + TATOVSET);
|
||||
/* Peripheral reset timeout, default 0xffffffff */
|
||||
iowrite32(0x0fffffff, base + PRTOVSET);
|
||||
/* Enable timeout counters */
|
||||
iowrite32(0x00000f00, base + DSICTRL);
|
||||
/* Interrupts not used, disable all */
|
||||
iowrite32(0, base + DSIINTE);
|
||||
/* DSI-Tx bias on */
|
||||
iowrite32(0x00000001, base + PHYCTRL);
|
||||
udelay(200);
|
||||
/* Deassert resets, power on, set multiplier */
|
||||
iowrite32(0x03070b01, base + PHYCTRL);
|
||||
/* Deassert resets, power on */
|
||||
iowrite32(0x03070001, base + PHYCTRL);
|
||||
|
||||
/*
|
||||
* Default = ULPS enable |
|
||||
* Contention detection enabled |
|
||||
* EoT packet transmission enable |
|
||||
* CRC check enable |
|
||||
* ECC check enable
|
||||
*/
|
||||
bitmap_fill((unsigned long *)&tmp, pdata->lane);
|
||||
tmp |= 0x00003700;
|
||||
iowrite32(tmp, base + SYSCONF);
|
||||
|
||||
/* setup l-bridge */
|
||||
|
||||
|
@ -316,18 +300,68 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
|
|||
* Non-burst mode with sync pulses: VSE and HSE are output,
|
||||
* HSA period allowed, no commands in LP
|
||||
*/
|
||||
vmctr2 = 0;
|
||||
if (pdata->flags & SH_MIPI_DSI_VSEE)
|
||||
vmctr2 |= 1 << 23;
|
||||
if (pdata->flags & SH_MIPI_DSI_HSEE)
|
||||
vmctr2 |= 1 << 22;
|
||||
if (pdata->flags & SH_MIPI_DSI_HSAE)
|
||||
vmctr2 |= 1 << 21;
|
||||
if (pdata->flags & SH_MIPI_DSI_BL2E)
|
||||
vmctr2 |= 1 << 17;
|
||||
if (pdata->flags & SH_MIPI_DSI_HSABM)
|
||||
vmctr2 |= 0x20;
|
||||
if (pdata->flags & SH_MIPI_DSI_HSPBM)
|
||||
vmctr2 |= 0x10;
|
||||
vmctr2 |= 1 << 5;
|
||||
if (pdata->flags & SH_MIPI_DSI_HBPBM)
|
||||
vmctr2 |= 1 << 4;
|
||||
if (pdata->flags & SH_MIPI_DSI_HFPBM)
|
||||
vmctr2 |= 1 << 3;
|
||||
iowrite32(vmctr2, mipi->linkbase + VMCTR2);
|
||||
|
||||
/*
|
||||
* 0x660 = 1632 bytes per line (RGB24, 544 pixels: see
|
||||
* sh_mobile_lcdc_info.ch[0].lcd_cfg[0].xres), HSALEN = 1 - default
|
||||
* (unused if VMCTR2[HSABM] = 0)
|
||||
* VMLEN1 = RGBLEN | HSALEN
|
||||
*
|
||||
* see
|
||||
* Video mode - Blanking Packet setting
|
||||
*/
|
||||
iowrite32(1 | (linelength << 16), mipi->linkbase + VMLEN1);
|
||||
top = linelength << 16; /* RGBLEN */
|
||||
bottom = 0x00000001;
|
||||
if (pdata->flags & SH_MIPI_DSI_HSABM) /* HSALEN */
|
||||
bottom = (pdata->lane * ch->lcd_cfg[0].hsync_len) - 10;
|
||||
iowrite32(top | bottom , mipi->linkbase + VMLEN1);
|
||||
|
||||
/*
|
||||
* VMLEN2 = HBPLEN | HFPLEN
|
||||
*
|
||||
* see
|
||||
* Video mode - Blanking Packet setting
|
||||
*/
|
||||
top = 0x00010000;
|
||||
bottom = 0x00000001;
|
||||
delay = 0;
|
||||
|
||||
div = 1; /* HSbyteCLK is calculation base
|
||||
* HS4divCLK = HSbyteCLK/2
|
||||
* HS6divCLK is not supported for now */
|
||||
if (pdata->flags & SH_MIPI_DSI_HS4divCLK)
|
||||
div = 2;
|
||||
|
||||
if (pdata->flags & SH_MIPI_DSI_HFPBM) { /* HBPLEN */
|
||||
top = ch->lcd_cfg[0].hsync_len + ch->lcd_cfg[0].left_margin;
|
||||
top = ((pdata->lane * top / div) - 10) << 16;
|
||||
}
|
||||
if (pdata->flags & SH_MIPI_DSI_HBPBM) { /* HFPLEN */
|
||||
bottom = ch->lcd_cfg[0].right_margin;
|
||||
bottom = (pdata->lane * bottom / div) - 12;
|
||||
}
|
||||
|
||||
bpp = linelength / ch->lcd_cfg[0].xres; /* byte / pixel */
|
||||
if ((pdata->lane / div) > bpp) {
|
||||
tmp = ch->lcd_cfg[0].xres / bpp; /* output cycle */
|
||||
tmp = ch->lcd_cfg[0].xres - tmp; /* (input - output) cycle */
|
||||
delay = (pdata->lane * tmp);
|
||||
}
|
||||
|
||||
iowrite32(top | (bottom + delay) , mipi->linkbase + VMLEN2);
|
||||
|
||||
msleep(5);
|
||||
|
||||
|
@ -352,9 +386,56 @@ static int __init sh_mipi_setup(struct sh_mipi *mipi,
|
|||
pixfmt << 4);
|
||||
sh_mipi_dcs(ch->chan, MIPI_DCS_SET_DISPLAY_ON);
|
||||
|
||||
/* Enable timeout counters */
|
||||
iowrite32(0x00000f00, base + DSICTRL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mipi_display_on(void *arg, struct fb_info *info)
|
||||
{
|
||||
struct sh_mipi *mipi = arg;
|
||||
struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data;
|
||||
int ret;
|
||||
|
||||
pm_runtime_get_sync(&mipi->pdev->dev);
|
||||
|
||||
ret = pdata->set_dot_clock(mipi->pdev, mipi->base, 1);
|
||||
if (ret < 0)
|
||||
goto mipi_display_on_fail1;
|
||||
|
||||
ret = sh_mipi_setup(mipi, pdata);
|
||||
if (ret < 0)
|
||||
goto mipi_display_on_fail2;
|
||||
|
||||
sh_mipi_dsi_enable(mipi, true);
|
||||
|
||||
if (mipi->next_display_on)
|
||||
mipi->next_display_on(mipi->next_board_data, info);
|
||||
|
||||
return;
|
||||
|
||||
mipi_display_on_fail1:
|
||||
pm_runtime_put_sync(&mipi->pdev->dev);
|
||||
mipi_display_on_fail2:
|
||||
pdata->set_dot_clock(mipi->pdev, mipi->base, 0);
|
||||
}
|
||||
|
||||
static void mipi_display_off(void *arg)
|
||||
{
|
||||
struct sh_mipi *mipi = arg;
|
||||
struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data;
|
||||
|
||||
if (mipi->next_display_off)
|
||||
mipi->next_display_off(mipi->next_board_data);
|
||||
|
||||
sh_mipi_dsi_enable(mipi, false);
|
||||
|
||||
pdata->set_dot_clock(mipi->pdev, mipi->base, 0);
|
||||
|
||||
pm_runtime_put_sync(&mipi->pdev->dev);
|
||||
}
|
||||
|
||||
static int __init sh_mipi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct sh_mipi *mipi;
|
||||
|
@ -363,11 +444,13 @@ static int __init sh_mipi_probe(struct platform_device *pdev)
|
|||
struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||
unsigned long rate, f_current;
|
||||
int idx = pdev->id, ret;
|
||||
char dsip_clk[] = "dsi.p_clk";
|
||||
|
||||
if (!res || !res2 || idx >= ARRAY_SIZE(mipi_dsi) || !pdata)
|
||||
return -ENODEV;
|
||||
|
||||
if (!pdata->set_dot_clock)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&array_lock);
|
||||
if (idx < 0)
|
||||
for (idx = 0; idx < ARRAY_SIZE(mipi_dsi) && mipi_dsi[idx]; idx++)
|
||||
|
@ -408,7 +491,7 @@ static int __init sh_mipi_probe(struct platform_device *pdev)
|
|||
goto emap2;
|
||||
}
|
||||
|
||||
mipi->dev = &pdev->dev;
|
||||
mipi->pdev = pdev;
|
||||
|
||||
mipi->dsit_clk = clk_get(&pdev->dev, "dsit_clk");
|
||||
if (IS_ERR(mipi->dsit_clk)) {
|
||||
|
@ -428,44 +511,15 @@ static int __init sh_mipi_probe(struct platform_device *pdev)
|
|||
|
||||
dev_dbg(&pdev->dev, "DSI-T clk %lu -> %lu\n", f_current, rate);
|
||||
|
||||
sprintf(dsip_clk, "dsi%1.1dp_clk", idx);
|
||||
mipi->dsip_clk = clk_get(&pdev->dev, dsip_clk);
|
||||
if (IS_ERR(mipi->dsip_clk)) {
|
||||
ret = PTR_ERR(mipi->dsip_clk);
|
||||
goto eclkpget;
|
||||
}
|
||||
|
||||
f_current = clk_get_rate(mipi->dsip_clk);
|
||||
/* Between 10 and 50MHz */
|
||||
rate = clk_round_rate(mipi->dsip_clk, 24000000);
|
||||
if (rate > 0 && rate != f_current)
|
||||
ret = clk_set_rate(mipi->dsip_clk, rate);
|
||||
else
|
||||
ret = rate;
|
||||
if (ret < 0)
|
||||
goto esetprate;
|
||||
|
||||
dev_dbg(&pdev->dev, "DSI-P clk %lu -> %lu\n", f_current, rate);
|
||||
|
||||
msleep(10);
|
||||
|
||||
ret = clk_enable(mipi->dsit_clk);
|
||||
if (ret < 0)
|
||||
goto eclkton;
|
||||
|
||||
ret = clk_enable(mipi->dsip_clk);
|
||||
if (ret < 0)
|
||||
goto eclkpon;
|
||||
|
||||
mipi_dsi[idx] = mipi;
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
pm_runtime_resume(&pdev->dev);
|
||||
|
||||
ret = sh_mipi_setup(mipi, pdata);
|
||||
if (ret < 0)
|
||||
goto emipisetup;
|
||||
|
||||
mutex_unlock(&array_lock);
|
||||
platform_set_drvdata(pdev, mipi);
|
||||
|
||||
|
@ -482,16 +536,7 @@ static int __init sh_mipi_probe(struct platform_device *pdev)
|
|||
|
||||
return 0;
|
||||
|
||||
emipisetup:
|
||||
mipi_dsi[idx] = NULL;
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
clk_disable(mipi->dsip_clk);
|
||||
eclkpon:
|
||||
clk_disable(mipi->dsit_clk);
|
||||
eclkton:
|
||||
esetprate:
|
||||
clk_put(mipi->dsip_clk);
|
||||
eclkpget:
|
||||
esettrate:
|
||||
clk_put(mipi->dsit_clk);
|
||||
eclktget:
|
||||
|
@ -542,10 +587,9 @@ static int __exit sh_mipi_remove(struct platform_device *pdev)
|
|||
pdata->lcd_chan->board_cfg.board_data = NULL;
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
clk_disable(mipi->dsip_clk);
|
||||
clk_disable(mipi->dsit_clk);
|
||||
clk_put(mipi->dsit_clk);
|
||||
clk_put(mipi->dsip_clk);
|
||||
|
||||
iounmap(mipi->linkbase);
|
||||
if (res2)
|
||||
release_mem_region(res2->start, resource_size(res2));
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -102,7 +103,7 @@ struct sh_mobile_lcdc_priv {
|
|||
struct sh_mobile_lcdc_chan ch[2];
|
||||
struct notifier_block notifier;
|
||||
int started;
|
||||
int forced_bpp; /* 2 channel LCDC must share bpp setting */
|
||||
int forced_fourcc; /* 2 channel LCDC must share fourcc setting */
|
||||
struct sh_mobile_meram_info *meram_dev;
|
||||
};
|
||||
|
||||
|
@ -215,6 +216,47 @@ struct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = {
|
|||
lcdc_sys_read_data,
|
||||
};
|
||||
|
||||
static int sh_mobile_format_fourcc(const struct fb_var_screeninfo *var)
|
||||
{
|
||||
if (var->grayscale > 1)
|
||||
return var->grayscale;
|
||||
|
||||
switch (var->bits_per_pixel) {
|
||||
case 16:
|
||||
return V4L2_PIX_FMT_RGB565;
|
||||
case 24:
|
||||
return V4L2_PIX_FMT_BGR24;
|
||||
case 32:
|
||||
return V4L2_PIX_FMT_BGR32;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int sh_mobile_format_is_fourcc(const struct fb_var_screeninfo *var)
|
||||
{
|
||||
return var->grayscale > 1;
|
||||
}
|
||||
|
||||
static bool sh_mobile_format_is_yuv(const struct fb_var_screeninfo *var)
|
||||
{
|
||||
if (var->grayscale <= 1)
|
||||
return false;
|
||||
|
||||
switch (var->grayscale) {
|
||||
case V4L2_PIX_FMT_NV12:
|
||||
case V4L2_PIX_FMT_NV21:
|
||||
case V4L2_PIX_FMT_NV16:
|
||||
case V4L2_PIX_FMT_NV61:
|
||||
case V4L2_PIX_FMT_NV24:
|
||||
case V4L2_PIX_FMT_NV42:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv)
|
||||
{
|
||||
if (atomic_inc_and_test(&priv->hw_usecnt)) {
|
||||
|
@ -420,7 +462,7 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
|
|||
tmp = ((display_var->xres & 7) << 24) |
|
||||
((display_h_total & 7) << 16) |
|
||||
((display_var->hsync_len & 7) << 8) |
|
||||
hsync_pos;
|
||||
(hsync_pos & 7);
|
||||
lcdc_write_chan(ch, LDHAJR, tmp);
|
||||
}
|
||||
|
||||
|
@ -435,7 +477,6 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
|
|||
{
|
||||
struct sh_mobile_lcdc_chan *ch;
|
||||
unsigned long tmp;
|
||||
int bpp = 0;
|
||||
int k, m;
|
||||
|
||||
/* Enable LCDC channels. Read data from external memory, avoid using the
|
||||
|
@ -454,9 +495,6 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
|
|||
if (!ch->enabled)
|
||||
continue;
|
||||
|
||||
if (!bpp)
|
||||
bpp = ch->info->var.bits_per_pixel;
|
||||
|
||||
/* Power supply */
|
||||
lcdc_write_chan(ch, LDPMR, 0);
|
||||
|
||||
|
@ -487,31 +525,37 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
|
|||
|
||||
sh_mobile_lcdc_geometry(ch);
|
||||
|
||||
if (ch->info->var.nonstd) {
|
||||
tmp = (ch->info->var.nonstd << 16);
|
||||
switch (ch->info->var.bits_per_pixel) {
|
||||
case 12:
|
||||
tmp |= LDDFR_YF_420;
|
||||
switch (sh_mobile_format_fourcc(&ch->info->var)) {
|
||||
case V4L2_PIX_FMT_RGB565:
|
||||
tmp = LDDFR_PKF_RGB16;
|
||||
break;
|
||||
case V4L2_PIX_FMT_BGR24:
|
||||
tmp = LDDFR_PKF_RGB24;
|
||||
break;
|
||||
case V4L2_PIX_FMT_BGR32:
|
||||
tmp = LDDFR_PKF_ARGB32;
|
||||
break;
|
||||
case V4L2_PIX_FMT_NV12:
|
||||
case V4L2_PIX_FMT_NV21:
|
||||
tmp = LDDFR_CC | LDDFR_YF_420;
|
||||
break;
|
||||
case V4L2_PIX_FMT_NV16:
|
||||
case V4L2_PIX_FMT_NV61:
|
||||
tmp = LDDFR_CC | LDDFR_YF_422;
|
||||
break;
|
||||
case V4L2_PIX_FMT_NV24:
|
||||
case V4L2_PIX_FMT_NV42:
|
||||
tmp = LDDFR_CC | LDDFR_YF_444;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sh_mobile_format_is_yuv(&ch->info->var)) {
|
||||
switch (ch->info->var.colorspace) {
|
||||
case V4L2_COLORSPACE_REC709:
|
||||
tmp |= LDDFR_CF1;
|
||||
break;
|
||||
case 16:
|
||||
tmp |= LDDFR_YF_422;
|
||||
break;
|
||||
case 24:
|
||||
default:
|
||||
tmp |= LDDFR_YF_444;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (ch->info->var.bits_per_pixel) {
|
||||
case 16:
|
||||
tmp = LDDFR_PKF_RGB16;
|
||||
break;
|
||||
case 24:
|
||||
tmp = LDDFR_PKF_RGB24;
|
||||
break;
|
||||
case 32:
|
||||
default:
|
||||
tmp = LDDFR_PKF_ARGB32;
|
||||
case V4L2_COLORSPACE_JPEG:
|
||||
tmp |= LDDFR_CF0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -519,7 +563,7 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
|
|||
lcdc_write_chan(ch, LDDFR, tmp);
|
||||
lcdc_write_chan(ch, LDMLSR, ch->pitch);
|
||||
lcdc_write_chan(ch, LDSA1R, ch->base_addr_y);
|
||||
if (ch->info->var.nonstd)
|
||||
if (sh_mobile_format_is_yuv(&ch->info->var))
|
||||
lcdc_write_chan(ch, LDSA2R, ch->base_addr_c);
|
||||
|
||||
/* When using deferred I/O mode, configure the LCDC for one-shot
|
||||
|
@ -536,21 +580,23 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
|
|||
}
|
||||
|
||||
/* Word and long word swap. */
|
||||
if (priv->ch[0].info->var.nonstd)
|
||||
switch (sh_mobile_format_fourcc(&priv->ch[0].info->var)) {
|
||||
case V4L2_PIX_FMT_RGB565:
|
||||
case V4L2_PIX_FMT_NV21:
|
||||
case V4L2_PIX_FMT_NV61:
|
||||
case V4L2_PIX_FMT_NV42:
|
||||
tmp = LDDDSR_LS | LDDDSR_WS;
|
||||
break;
|
||||
case V4L2_PIX_FMT_BGR24:
|
||||
case V4L2_PIX_FMT_NV12:
|
||||
case V4L2_PIX_FMT_NV16:
|
||||
case V4L2_PIX_FMT_NV24:
|
||||
tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
|
||||
else {
|
||||
switch (bpp) {
|
||||
case 16:
|
||||
tmp = LDDDSR_LS | LDDDSR_WS;
|
||||
break;
|
||||
case 24:
|
||||
tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS;
|
||||
break;
|
||||
case 32:
|
||||
default:
|
||||
tmp = LDDDSR_LS;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case V4L2_PIX_FMT_BGR32:
|
||||
default:
|
||||
tmp = LDDDSR_LS;
|
||||
break;
|
||||
}
|
||||
lcdc_write(priv, _LDDDSR, tmp);
|
||||
|
||||
|
@ -622,12 +668,24 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
|
|||
ch->meram_enabled = 0;
|
||||
}
|
||||
|
||||
if (!ch->info->var.nonstd)
|
||||
pixelformat = SH_MOBILE_MERAM_PF_RGB;
|
||||
else if (ch->info->var.bits_per_pixel == 24)
|
||||
pixelformat = SH_MOBILE_MERAM_PF_NV24;
|
||||
else
|
||||
switch (sh_mobile_format_fourcc(&ch->info->var)) {
|
||||
case V4L2_PIX_FMT_NV12:
|
||||
case V4L2_PIX_FMT_NV21:
|
||||
case V4L2_PIX_FMT_NV16:
|
||||
case V4L2_PIX_FMT_NV61:
|
||||
pixelformat = SH_MOBILE_MERAM_PF_NV;
|
||||
break;
|
||||
case V4L2_PIX_FMT_NV24:
|
||||
case V4L2_PIX_FMT_NV42:
|
||||
pixelformat = SH_MOBILE_MERAM_PF_NV24;
|
||||
break;
|
||||
case V4L2_PIX_FMT_RGB565:
|
||||
case V4L2_PIX_FMT_BGR24:
|
||||
case V4L2_PIX_FMT_BGR32:
|
||||
default:
|
||||
pixelformat = SH_MOBILE_MERAM_PF_RGB;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = mdev->ops->meram_register(mdev, cfg, ch->pitch,
|
||||
ch->info->var.yres, pixelformat,
|
||||
|
@ -845,6 +903,7 @@ static struct fb_fix_screeninfo sh_mobile_lcdc_fix = {
|
|||
.xpanstep = 0,
|
||||
.ypanstep = 1,
|
||||
.ywrapstep = 0,
|
||||
.capabilities = FB_CAP_FOURCC,
|
||||
};
|
||||
|
||||
static void sh_mobile_lcdc_fillrect(struct fb_info *info,
|
||||
|
@ -877,8 +936,9 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
|
|||
unsigned long new_pan_offset;
|
||||
unsigned long base_addr_y, base_addr_c;
|
||||
unsigned long c_offset;
|
||||
bool yuv = sh_mobile_format_is_yuv(&info->var);
|
||||
|
||||
if (!info->var.nonstd)
|
||||
if (!yuv)
|
||||
new_pan_offset = var->yoffset * info->fix.line_length
|
||||
+ var->xoffset * (info->var.bits_per_pixel / 8);
|
||||
else
|
||||
|
@ -892,7 +952,7 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
|
|||
|
||||
/* Set the source address for the next refresh */
|
||||
base_addr_y = ch->dma_handle + new_pan_offset;
|
||||
if (info->var.nonstd) {
|
||||
if (yuv) {
|
||||
/* Set y offset */
|
||||
c_offset = var->yoffset * info->fix.line_length
|
||||
* (info->var.bits_per_pixel - 8) / 8;
|
||||
|
@ -900,7 +960,7 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
|
|||
+ info->var.xres * info->var.yres_virtual
|
||||
+ c_offset;
|
||||
/* Set x offset */
|
||||
if (info->var.bits_per_pixel == 24)
|
||||
if (sh_mobile_format_fourcc(&info->var) == V4L2_PIX_FMT_NV24)
|
||||
base_addr_c += 2 * var->xoffset;
|
||||
else
|
||||
base_addr_c += var->xoffset;
|
||||
|
@ -924,7 +984,7 @@ static int sh_mobile_fb_pan_display(struct fb_var_screeninfo *var,
|
|||
ch->base_addr_c = base_addr_c;
|
||||
|
||||
lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y);
|
||||
if (info->var.nonstd)
|
||||
if (yuv)
|
||||
lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c);
|
||||
|
||||
if (lcdc_chan_is_sublcd(ch))
|
||||
|
@ -1100,51 +1160,84 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in
|
|||
if (var->yres_virtual < var->yres)
|
||||
var->yres_virtual = var->yres;
|
||||
|
||||
if (var->bits_per_pixel <= 16) { /* RGB 565 */
|
||||
var->bits_per_pixel = 16;
|
||||
var->red.offset = 11;
|
||||
var->red.length = 5;
|
||||
var->green.offset = 5;
|
||||
var->green.length = 6;
|
||||
var->blue.offset = 0;
|
||||
var->blue.length = 5;
|
||||
var->transp.offset = 0;
|
||||
var->transp.length = 0;
|
||||
} else if (var->bits_per_pixel <= 24) { /* RGB 888 */
|
||||
var->bits_per_pixel = 24;
|
||||
var->red.offset = 16;
|
||||
var->red.length = 8;
|
||||
var->green.offset = 8;
|
||||
var->green.length = 8;
|
||||
var->blue.offset = 0;
|
||||
var->blue.length = 8;
|
||||
var->transp.offset = 0;
|
||||
var->transp.length = 0;
|
||||
} else if (var->bits_per_pixel <= 32) { /* RGBA 888 */
|
||||
var->bits_per_pixel = 32;
|
||||
var->red.offset = 16;
|
||||
var->red.length = 8;
|
||||
var->green.offset = 8;
|
||||
var->green.length = 8;
|
||||
var->blue.offset = 0;
|
||||
var->blue.length = 8;
|
||||
var->transp.offset = 24;
|
||||
var->transp.length = 8;
|
||||
} else
|
||||
return -EINVAL;
|
||||
if (sh_mobile_format_is_fourcc(var)) {
|
||||
switch (var->grayscale) {
|
||||
case V4L2_PIX_FMT_NV12:
|
||||
case V4L2_PIX_FMT_NV21:
|
||||
var->bits_per_pixel = 12;
|
||||
break;
|
||||
case V4L2_PIX_FMT_RGB565:
|
||||
case V4L2_PIX_FMT_NV16:
|
||||
case V4L2_PIX_FMT_NV61:
|
||||
var->bits_per_pixel = 16;
|
||||
break;
|
||||
case V4L2_PIX_FMT_BGR24:
|
||||
case V4L2_PIX_FMT_NV24:
|
||||
case V4L2_PIX_FMT_NV42:
|
||||
var->bits_per_pixel = 24;
|
||||
break;
|
||||
case V4L2_PIX_FMT_BGR32:
|
||||
var->bits_per_pixel = 32;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
var->red.msb_right = 0;
|
||||
var->green.msb_right = 0;
|
||||
var->blue.msb_right = 0;
|
||||
var->transp.msb_right = 0;
|
||||
/* Default to RGB and JPEG color-spaces for RGB and YUV formats
|
||||
* respectively.
|
||||
*/
|
||||
if (!sh_mobile_format_is_yuv(var))
|
||||
var->colorspace = V4L2_COLORSPACE_SRGB;
|
||||
else if (var->colorspace != V4L2_COLORSPACE_REC709)
|
||||
var->colorspace = V4L2_COLORSPACE_JPEG;
|
||||
} else {
|
||||
if (var->bits_per_pixel <= 16) { /* RGB 565 */
|
||||
var->bits_per_pixel = 16;
|
||||
var->red.offset = 11;
|
||||
var->red.length = 5;
|
||||
var->green.offset = 5;
|
||||
var->green.length = 6;
|
||||
var->blue.offset = 0;
|
||||
var->blue.length = 5;
|
||||
var->transp.offset = 0;
|
||||
var->transp.length = 0;
|
||||
} else if (var->bits_per_pixel <= 24) { /* RGB 888 */
|
||||
var->bits_per_pixel = 24;
|
||||
var->red.offset = 16;
|
||||
var->red.length = 8;
|
||||
var->green.offset = 8;
|
||||
var->green.length = 8;
|
||||
var->blue.offset = 0;
|
||||
var->blue.length = 8;
|
||||
var->transp.offset = 0;
|
||||
var->transp.length = 0;
|
||||
} else if (var->bits_per_pixel <= 32) { /* RGBA 888 */
|
||||
var->bits_per_pixel = 32;
|
||||
var->red.offset = 16;
|
||||
var->red.length = 8;
|
||||
var->green.offset = 8;
|
||||
var->green.length = 8;
|
||||
var->blue.offset = 0;
|
||||
var->blue.length = 8;
|
||||
var->transp.offset = 24;
|
||||
var->transp.length = 8;
|
||||
} else
|
||||
return -EINVAL;
|
||||
|
||||
var->red.msb_right = 0;
|
||||
var->green.msb_right = 0;
|
||||
var->blue.msb_right = 0;
|
||||
var->transp.msb_right = 0;
|
||||
}
|
||||
|
||||
/* Make sure we don't exceed our allocated memory. */
|
||||
if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 >
|
||||
info->fix.smem_len)
|
||||
return -EINVAL;
|
||||
|
||||
/* only accept the forced_bpp for dual channel configurations */
|
||||
if (p->forced_bpp && p->forced_bpp != var->bits_per_pixel)
|
||||
/* only accept the forced_fourcc for dual channel configurations */
|
||||
if (p->forced_fourcc &&
|
||||
p->forced_fourcc != sh_mobile_format_fourcc(var))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
|
@ -1158,7 +1251,7 @@ static int sh_mobile_set_par(struct fb_info *info)
|
|||
|
||||
sh_mobile_lcdc_stop(ch->lcdc);
|
||||
|
||||
if (info->var.nonstd)
|
||||
if (sh_mobile_format_is_yuv(&info->var))
|
||||
info->fix.line_length = info->var.xres;
|
||||
else
|
||||
info->fix.line_length = info->var.xres
|
||||
|
@ -1170,6 +1263,14 @@ static int sh_mobile_set_par(struct fb_info *info)
|
|||
info->fix.line_length = line_length;
|
||||
}
|
||||
|
||||
if (sh_mobile_format_is_fourcc(&info->var)) {
|
||||
info->fix.type = FB_TYPE_FOURCC;
|
||||
info->fix.visual = FB_VISUAL_FOURCC;
|
||||
} else {
|
||||
info->fix.type = FB_TYPE_PACKED_PIXELS;
|
||||
info->fix.visual = FB_VISUAL_TRUECOLOR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1464,9 +1565,9 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
|
|||
for (i = 0, mode = cfg->lcd_cfg; i < cfg->num_cfg; i++, mode++) {
|
||||
unsigned int size = mode->yres * mode->xres;
|
||||
|
||||
/* NV12 buffers must have even number of lines */
|
||||
if ((cfg->nonstd) && cfg->bpp == 12 &&
|
||||
(mode->yres & 0x1)) {
|
||||
/* NV12/NV21 buffers must have even number of lines */
|
||||
if ((cfg->fourcc == V4L2_PIX_FMT_NV12 ||
|
||||
cfg->fourcc == V4L2_PIX_FMT_NV21) && (mode->yres & 0x1)) {
|
||||
dev_err(dev, "yres must be multiple of 2 for YCbCr420 "
|
||||
"mode.\n");
|
||||
return -EINVAL;
|
||||
|
@ -1484,14 +1585,6 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
|
|||
dev_dbg(dev, "Found largest videomode %ux%u\n",
|
||||
max_mode->xres, max_mode->yres);
|
||||
|
||||
/* Initialize fixed screen information. Restrict pan to 2 lines steps
|
||||
* for NV12.
|
||||
*/
|
||||
info->fix = sh_mobile_lcdc_fix;
|
||||
info->fix.smem_len = max_size * 2 * cfg->bpp / 8;
|
||||
if (cfg->nonstd && cfg->bpp == 12)
|
||||
info->fix.ypanstep = 2;
|
||||
|
||||
/* Create the mode list. */
|
||||
if (cfg->lcd_cfg == NULL) {
|
||||
mode = &default_720p;
|
||||
|
@ -1509,19 +1602,38 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
|
|||
*/
|
||||
var = &info->var;
|
||||
fb_videomode_to_var(var, mode);
|
||||
var->bits_per_pixel = cfg->bpp;
|
||||
var->width = cfg->lcd_size_cfg.width;
|
||||
var->height = cfg->lcd_size_cfg.height;
|
||||
var->yres_virtual = var->yres * 2;
|
||||
var->activate = FB_ACTIVATE_NOW;
|
||||
|
||||
switch (cfg->fourcc) {
|
||||
case V4L2_PIX_FMT_RGB565:
|
||||
var->bits_per_pixel = 16;
|
||||
break;
|
||||
case V4L2_PIX_FMT_BGR24:
|
||||
var->bits_per_pixel = 24;
|
||||
break;
|
||||
case V4L2_PIX_FMT_BGR32:
|
||||
var->bits_per_pixel = 32;
|
||||
break;
|
||||
default:
|
||||
var->grayscale = cfg->fourcc;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Make sure the memory size check won't fail. smem_len is initialized
|
||||
* later based on var.
|
||||
*/
|
||||
info->fix.smem_len = UINT_MAX;
|
||||
ret = sh_mobile_check_var(var, info);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
max_size = max_size * var->bits_per_pixel / 8 * 2;
|
||||
|
||||
/* Allocate frame buffer memory and color map. */
|
||||
buf = dma_alloc_coherent(dev, info->fix.smem_len, &ch->dma_handle,
|
||||
GFP_KERNEL);
|
||||
buf = dma_alloc_coherent(dev, max_size, &ch->dma_handle, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
dev_err(dev, "unable to allocate buffer\n");
|
||||
return -ENOMEM;
|
||||
|
@ -1530,16 +1642,27 @@ static int __devinit sh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch,
|
|||
ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "unable to allocate cmap\n");
|
||||
dma_free_coherent(dev, info->fix.smem_len,
|
||||
buf, ch->dma_handle);
|
||||
dma_free_coherent(dev, max_size, buf, ch->dma_handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Initialize fixed screen information. Restrict pan to 2 lines steps
|
||||
* for NV12 and NV21.
|
||||
*/
|
||||
info->fix = sh_mobile_lcdc_fix;
|
||||
info->fix.smem_start = ch->dma_handle;
|
||||
if (var->nonstd)
|
||||
info->fix.smem_len = max_size;
|
||||
if (cfg->fourcc == V4L2_PIX_FMT_NV12 ||
|
||||
cfg->fourcc == V4L2_PIX_FMT_NV21)
|
||||
info->fix.ypanstep = 2;
|
||||
|
||||
if (sh_mobile_format_is_yuv(var)) {
|
||||
info->fix.line_length = var->xres;
|
||||
else
|
||||
info->fix.line_length = var->xres * (cfg->bpp / 8);
|
||||
info->fix.visual = FB_VISUAL_FOURCC;
|
||||
} else {
|
||||
info->fix.line_length = var->xres * var->bits_per_pixel / 8;
|
||||
info->fix.visual = FB_VISUAL_TRUECOLOR;
|
||||
}
|
||||
|
||||
info->screen_base = buf;
|
||||
info->device = dev;
|
||||
|
@ -1626,9 +1749,9 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
|
|||
goto err1;
|
||||
}
|
||||
|
||||
/* for dual channel LCDC (MAIN + SUB) force shared bpp setting */
|
||||
/* for dual channel LCDC (MAIN + SUB) force shared format setting */
|
||||
if (num_channels == 2)
|
||||
priv->forced_bpp = pdata->ch[0].bpp;
|
||||
priv->forced_fourcc = pdata->ch[0].fourcc;
|
||||
|
||||
priv->base = ioremap_nocache(res->start, resource_size(res));
|
||||
if (!priv->base)
|
||||
|
@ -1675,13 +1798,10 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
|
|||
if (error < 0)
|
||||
goto err1;
|
||||
|
||||
dev_info(info->dev,
|
||||
"registered %s/%s as %dx%d %dbpp.\n",
|
||||
pdev->name,
|
||||
(ch->cfg.chan == LCDC_CHAN_MAINLCD) ?
|
||||
"mainlcd" : "sublcd",
|
||||
info->var.xres, info->var.yres,
|
||||
ch->cfg.bpp);
|
||||
dev_info(info->dev, "registered %s/%s as %dx%d %dbpp.\n",
|
||||
pdev->name, (ch->cfg.chan == LCDC_CHAN_MAINLCD) ?
|
||||
"mainlcd" : "sublcd", info->var.xres, info->var.yres,
|
||||
info->var.bits_per_pixel);
|
||||
|
||||
/* deferred io mode: disable clock to save power */
|
||||
if (info->fbdefio || info->state == FBINFO_STATE_SUSPENDED)
|
||||
|
@ -1709,18 +1829,7 @@ static struct platform_driver sh_mobile_lcdc_driver = {
|
|||
.remove = sh_mobile_lcdc_remove,
|
||||
};
|
||||
|
||||
static int __init sh_mobile_lcdc_init(void)
|
||||
{
|
||||
return platform_driver_register(&sh_mobile_lcdc_driver);
|
||||
}
|
||||
|
||||
static void __exit sh_mobile_lcdc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&sh_mobile_lcdc_driver);
|
||||
}
|
||||
|
||||
module_init(sh_mobile_lcdc_init);
|
||||
module_exit(sh_mobile_lcdc_exit);
|
||||
module_platform_driver(sh_mobile_lcdc_driver);
|
||||
|
||||
MODULE_DESCRIPTION("SuperH Mobile LCDC Framebuffer driver");
|
||||
MODULE_AUTHOR("Magnus Damm <damm@opensource.se>");
|
||||
|
|
|
@ -679,18 +679,7 @@ static struct platform_driver sh_mobile_meram_driver = {
|
|||
.remove = sh_mobile_meram_remove,
|
||||
};
|
||||
|
||||
static int __init sh_mobile_meram_init(void)
|
||||
{
|
||||
return platform_driver_register(&sh_mobile_meram_driver);
|
||||
}
|
||||
|
||||
static void __exit sh_mobile_meram_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&sh_mobile_meram_driver);
|
||||
}
|
||||
|
||||
module_init(sh_mobile_meram_init);
|
||||
module_exit(sh_mobile_meram_exit);
|
||||
module_platform_driver(sh_mobile_meram_driver);
|
||||
|
||||
MODULE_DESCRIPTION("SuperH Mobile MERAM driver");
|
||||
MODULE_AUTHOR("Damian Hobson-Garcia / Takanari Hayama");
|
||||
|
|
|
@ -2230,18 +2230,7 @@ static struct platform_driver sm501fb_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __devinit sm501fb_init(void)
|
||||
{
|
||||
return platform_driver_register(&sm501fb_driver);
|
||||
}
|
||||
|
||||
static void __exit sm501fb_cleanup(void)
|
||||
{
|
||||
platform_driver_unregister(&sm501fb_driver);
|
||||
}
|
||||
|
||||
module_init(sm501fb_init);
|
||||
module_exit(sm501fb_cleanup);
|
||||
module_platform_driver(sm501fb_driver);
|
||||
|
||||
module_param_named(mode, fb_mode, charp, 0);
|
||||
MODULE_PARM_DESC(mode,
|
||||
|
|
|
@ -457,18 +457,7 @@ static struct platform_driver vt8500lcd_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init vt8500lcd_init(void)
|
||||
{
|
||||
return platform_driver_register(&vt8500lcd_driver);
|
||||
}
|
||||
|
||||
static void __exit vt8500lcd_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&vt8500lcd_driver);
|
||||
}
|
||||
|
||||
module_init(vt8500lcd_init);
|
||||
module_exit(vt8500lcd_exit);
|
||||
module_platform_driver(vt8500lcd_driver);
|
||||
|
||||
MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
|
||||
MODULE_DESCRIPTION("LCD controller driver for VIA VT8500");
|
||||
|
|
|
@ -1620,18 +1620,7 @@ static struct platform_driver w100fb_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
int __init w100fb_init(void)
|
||||
{
|
||||
return platform_driver_register(&w100fb_driver);
|
||||
}
|
||||
|
||||
void __exit w100fb_cleanup(void)
|
||||
{
|
||||
platform_driver_unregister(&w100fb_driver);
|
||||
}
|
||||
|
||||
module_init(w100fb_init);
|
||||
module_exit(w100fb_cleanup);
|
||||
module_platform_driver(w100fb_driver);
|
||||
|
||||
MODULE_DESCRIPTION("ATI Imageon w100 framebuffer driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -404,18 +404,7 @@ static struct platform_driver wm8505fb_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init wm8505fb_init(void)
|
||||
{
|
||||
return platform_driver_register(&wm8505fb_driver);
|
||||
}
|
||||
|
||||
static void __exit wm8505fb_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&wm8505fb_driver);
|
||||
}
|
||||
|
||||
module_init(wm8505fb_init);
|
||||
module_exit(wm8505fb_exit);
|
||||
module_platform_driver(wm8505fb_driver);
|
||||
|
||||
MODULE_AUTHOR("Ed Spiridonov <edo.rus@gmail.com>");
|
||||
MODULE_DESCRIPTION("Framebuffer driver for WMT WM8505");
|
||||
|
|
|
@ -167,18 +167,7 @@ static struct platform_driver wmt_ge_rops_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
static int __init wmt_ge_rops_init(void)
|
||||
{
|
||||
return platform_driver_register(&wmt_ge_rops_driver);
|
||||
}
|
||||
|
||||
static void __exit wmt_ge_rops_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&wmt_ge_rops_driver);
|
||||
}
|
||||
|
||||
module_init(wmt_ge_rops_init);
|
||||
module_exit(wmt_ge_rops_exit);
|
||||
module_platform_driver(wmt_ge_rops_driver);
|
||||
|
||||
MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com");
|
||||
MODULE_DESCRIPTION("Accelerators for raster operations using "
|
||||
|
|
|
@ -511,25 +511,7 @@ static struct platform_driver xilinxfb_of_driver = {
|
|||
},
|
||||
};
|
||||
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Module setup and teardown
|
||||
*/
|
||||
|
||||
static int __init
|
||||
xilinxfb_init(void)
|
||||
{
|
||||
return platform_driver_register(&xilinxfb_of_driver);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
xilinxfb_cleanup(void)
|
||||
{
|
||||
platform_driver_unregister(&xilinxfb_of_driver);
|
||||
}
|
||||
|
||||
module_init(xilinxfb_init);
|
||||
module_exit(xilinxfb_cleanup);
|
||||
module_platform_driver(xilinxfb_of_driver);
|
||||
|
||||
MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
|
||||
MODULE_DESCRIPTION("Xilinx TFT frame buffer driver");
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2006 James Simmons <jsimmons@infradead.org>
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
*
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_DISPLAY_H
|
||||
#define _LINUX_DISPLAY_H
|
||||
|
||||
#include <linux/device.h>
|
||||
|
||||
struct display_device;
|
||||
|
||||
/* This structure defines all the properties of a Display. */
|
||||
struct display_driver {
|
||||
int (*set_contrast)(struct display_device *, unsigned int);
|
||||
int (*get_contrast)(struct display_device *);
|
||||
void (*suspend)(struct display_device *, pm_message_t state);
|
||||
void (*resume)(struct display_device *);
|
||||
int (*probe)(struct display_device *, void *);
|
||||
int (*remove)(struct display_device *);
|
||||
int max_contrast;
|
||||
};
|
||||
|
||||
struct display_device {
|
||||
struct module *owner; /* Owner module */
|
||||
struct display_driver *driver;
|
||||
struct device *parent; /* This is the parent */
|
||||
struct device *dev; /* This is this display device */
|
||||
struct mutex lock;
|
||||
void *priv_data;
|
||||
char type[16];
|
||||
char *name;
|
||||
int idx;
|
||||
};
|
||||
|
||||
extern struct display_device *display_device_register(struct display_driver *driver,
|
||||
struct device *dev, void *devdata);
|
||||
extern void display_device_unregister(struct display_device *dev);
|
||||
|
||||
extern int probe_edid(struct display_device *dev, void *devdata);
|
||||
|
||||
#define to_display_device(obj) container_of(obj, struct display_device, class_dev)
|
||||
|
||||
#endif
|
|
@ -45,6 +45,7 @@
|
|||
#define FB_TYPE_INTERLEAVED_PLANES 2 /* Interleaved planes */
|
||||
#define FB_TYPE_TEXT 3 /* Text/attributes */
|
||||
#define FB_TYPE_VGA_PLANES 4 /* EGA/VGA planes */
|
||||
#define FB_TYPE_FOURCC 5 /* Type identified by a V4L2 FOURCC */
|
||||
|
||||
#define FB_AUX_TEXT_MDA 0 /* Monochrome text */
|
||||
#define FB_AUX_TEXT_CGA 1 /* CGA/EGA/VGA Color text */
|
||||
|
@ -69,6 +70,7 @@
|
|||
#define FB_VISUAL_PSEUDOCOLOR 3 /* Pseudo color (like atari) */
|
||||
#define FB_VISUAL_DIRECTCOLOR 4 /* Direct color */
|
||||
#define FB_VISUAL_STATIC_PSEUDOCOLOR 5 /* Pseudo color readonly */
|
||||
#define FB_VISUAL_FOURCC 6 /* Visual identified by a V4L2 FOURCC */
|
||||
|
||||
#define FB_ACCEL_NONE 0 /* no hardware accelerator */
|
||||
#define FB_ACCEL_ATARIBLITT 1 /* Atari Blitter */
|
||||
|
@ -154,6 +156,8 @@
|
|||
|
||||
#define FB_ACCEL_PUV3_UNIGFX 0xa0 /* PKUnity-v3 Unigfx */
|
||||
|
||||
#define FB_CAP_FOURCC 1 /* Device supports FOURCC-based formats */
|
||||
|
||||
struct fb_fix_screeninfo {
|
||||
char id[16]; /* identification string eg "TT Builtin" */
|
||||
unsigned long smem_start; /* Start of frame buffer mem */
|
||||
|
@ -171,7 +175,8 @@ struct fb_fix_screeninfo {
|
|||
__u32 mmio_len; /* Length of Memory Mapped I/O */
|
||||
__u32 accel; /* Indicate to driver which */
|
||||
/* specific chip/card we have */
|
||||
__u16 reserved[3]; /* Reserved for future compatibility */
|
||||
__u16 capabilities; /* see FB_CAP_* */
|
||||
__u16 reserved[2]; /* Reserved for future compatibility */
|
||||
};
|
||||
|
||||
/* Interpretation of offset for color fields: All offsets are from the right,
|
||||
|
@ -246,8 +251,8 @@ struct fb_var_screeninfo {
|
|||
__u32 yoffset; /* resolution */
|
||||
|
||||
__u32 bits_per_pixel; /* guess what */
|
||||
__u32 grayscale; /* != 0 Graylevels instead of colors */
|
||||
|
||||
__u32 grayscale; /* 0 = color, 1 = grayscale, */
|
||||
/* >1 = FOURCC */
|
||||
struct fb_bitfield red; /* bitfield in fb mem if true color, */
|
||||
struct fb_bitfield green; /* else only length is significant */
|
||||
struct fb_bitfield blue;
|
||||
|
@ -273,7 +278,8 @@ struct fb_var_screeninfo {
|
|||
__u32 sync; /* see FB_SYNC_* */
|
||||
__u32 vmode; /* see FB_VMODE_* */
|
||||
__u32 rotate; /* angle we rotate counter clockwise */
|
||||
__u32 reserved[5]; /* Reserved for future compatibility */
|
||||
__u32 colorspace; /* colorspace for FOURCC-based modes */
|
||||
__u32 reserved[4]; /* Reserved for future compatibility */
|
||||
};
|
||||
|
||||
struct fb_cmap {
|
||||
|
|
|
@ -343,6 +343,8 @@ struct v4l2_pix_format {
|
|||
#define V4L2_PIX_FMT_NV21 v4l2_fourcc('N', 'V', '2', '1') /* 12 Y/CrCb 4:2:0 */
|
||||
#define V4L2_PIX_FMT_NV16 v4l2_fourcc('N', 'V', '1', '6') /* 16 Y/CbCr 4:2:2 */
|
||||
#define V4L2_PIX_FMT_NV61 v4l2_fourcc('N', 'V', '6', '1') /* 16 Y/CrCb 4:2:2 */
|
||||
#define V4L2_PIX_FMT_NV24 v4l2_fourcc('N', 'V', '2', '4') /* 24 Y/CbCr 4:4:4 */
|
||||
#define V4L2_PIX_FMT_NV42 v4l2_fourcc('N', 'V', '4', '2') /* 24 Y/CrCb 4:4:4 */
|
||||
|
||||
/* two non contiguous planes - one Y, one Cr + Cb interleaved */
|
||||
#define V4L2_PIX_FMT_NV12M v4l2_fourcc('N', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 */
|
||||
|
|
|
@ -360,8 +360,8 @@
|
|||
#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM ZORRO_ID(VILLAGE_TRONIC, 0x0B, 0)
|
||||
#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG ZORRO_ID(VILLAGE_TRONIC, 0x0C, 0)
|
||||
#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_SEGMENTED_MODE ZORRO_ID(VILLAGE_TRONIC, 0x0D, 0)
|
||||
#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_MEM1 ZORRO_ID(VILLAGE_TRONIC, 0x15, 0)
|
||||
#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_MEM2 ZORRO_ID(VILLAGE_TRONIC, 0x16, 0)
|
||||
#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM1 ZORRO_ID(VILLAGE_TRONIC, 0x15, 0)
|
||||
#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_RAM2 ZORRO_ID(VILLAGE_TRONIC, 0x16, 0)
|
||||
#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z2_REG ZORRO_ID(VILLAGE_TRONIC, 0x17, 0)
|
||||
#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3 ZORRO_ID(VILLAGE_TRONIC, 0x18, 0)
|
||||
#define ZORRO_PROD_VILLAGE_TRONIC_ARIADNE ZORRO_ID(VILLAGE_TRONIC, 0xC9, 0)
|
||||
|
|
|
@ -200,6 +200,10 @@ enum omap_dss_clk_source {
|
|||
OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI, /* OMAP4: PLL2_CLK2 */
|
||||
};
|
||||
|
||||
enum omap_hdmi_flags {
|
||||
OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP = 1 << 0,
|
||||
};
|
||||
|
||||
/* RFBI */
|
||||
|
||||
struct rfbi_timings {
|
||||
|
@ -294,8 +298,8 @@ int dsi_vc_set_max_rx_packet_size(struct omap_dss_device *dssdev, int channel,
|
|||
u16 len);
|
||||
int dsi_vc_send_null(struct omap_dss_device *dssdev, int channel);
|
||||
int dsi_vc_send_bta_sync(struct omap_dss_device *dssdev, int channel);
|
||||
int dsi_video_mode_enable(struct omap_dss_device *dssdev, int channel);
|
||||
void dsi_video_mode_disable(struct omap_dss_device *dssdev, int channel);
|
||||
int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel);
|
||||
void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel);
|
||||
|
||||
/* Board specific data */
|
||||
struct omap_dss_board_info {
|
||||
|
@ -309,6 +313,8 @@ struct omap_dss_board_info {
|
|||
|
||||
/* Init with the board info */
|
||||
extern int omap_display_init(struct omap_dss_board_info *board_data);
|
||||
/* HDMI mux init*/
|
||||
extern int omap_hdmi_init(enum omap_hdmi_flags flags);
|
||||
|
||||
struct omap_display_platform_data {
|
||||
struct omap_dss_board_info *board_data;
|
||||
|
@ -352,8 +358,6 @@ struct omap_dss_cpr_coefs {
|
|||
};
|
||||
|
||||
struct omap_overlay_info {
|
||||
bool enabled;
|
||||
|
||||
u32 paddr;
|
||||
u32 p_uv_addr; /* for NV12 format */
|
||||
u16 screen_width;
|
||||
|
@ -385,11 +389,21 @@ struct omap_overlay {
|
|||
|
||||
/* dynamic fields */
|
||||
struct omap_overlay_manager *manager;
|
||||
struct omap_overlay_info info;
|
||||
|
||||
bool manager_changed;
|
||||
/* if true, info has been changed, but not applied() yet */
|
||||
bool info_dirty;
|
||||
/*
|
||||
* The following functions do not block:
|
||||
*
|
||||
* is_enabled
|
||||
* set_overlay_info
|
||||
* get_overlay_info
|
||||
*
|
||||
* The rest of the functions may block and cannot be called from
|
||||
* interrupt context
|
||||
*/
|
||||
|
||||
int (*enable)(struct omap_overlay *ovl);
|
||||
int (*disable)(struct omap_overlay *ovl);
|
||||
bool (*is_enabled)(struct omap_overlay *ovl);
|
||||
|
||||
int (*set_manager)(struct omap_overlay *ovl,
|
||||
struct omap_overlay_manager *mgr);
|
||||
|
@ -418,23 +432,27 @@ struct omap_overlay_manager_info {
|
|||
|
||||
struct omap_overlay_manager {
|
||||
struct kobject kobj;
|
||||
struct list_head list;
|
||||
|
||||
/* static fields */
|
||||
const char *name;
|
||||
enum omap_channel id;
|
||||
enum omap_overlay_manager_caps caps;
|
||||
int num_overlays;
|
||||
struct omap_overlay **overlays;
|
||||
struct list_head overlays;
|
||||
enum omap_display_type supported_displays;
|
||||
|
||||
/* dynamic fields */
|
||||
struct omap_dss_device *device;
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
bool device_changed;
|
||||
/* if true, info has been changed but not applied() yet */
|
||||
bool info_dirty;
|
||||
/*
|
||||
* The following functions do not block:
|
||||
*
|
||||
* set_manager_info
|
||||
* get_manager_info
|
||||
* apply
|
||||
*
|
||||
* The rest of the functions may block and cannot be called from
|
||||
* interrupt context
|
||||
*/
|
||||
|
||||
int (*set_device)(struct omap_overlay_manager *mgr,
|
||||
struct omap_dss_device *dssdev);
|
||||
|
@ -448,9 +466,6 @@ struct omap_overlay_manager {
|
|||
int (*apply)(struct omap_overlay_manager *mgr);
|
||||
int (*wait_for_go)(struct omap_overlay_manager *mgr);
|
||||
int (*wait_for_vsync)(struct omap_overlay_manager *mgr);
|
||||
|
||||
int (*enable)(struct omap_overlay_manager *mgr);
|
||||
int (*disable)(struct omap_overlay_manager *mgr);
|
||||
};
|
||||
|
||||
struct omap_dss_device {
|
||||
|
@ -662,12 +677,7 @@ void omapdss_dsi_vc_enable_hs(struct omap_dss_device *dssdev, int channel,
|
|||
bool enable);
|
||||
int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable);
|
||||
|
||||
int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
|
||||
u16 *x, u16 *y, u16 *w, u16 *h,
|
||||
bool enlarge_update_area);
|
||||
int omap_dsi_update(struct omap_dss_device *dssdev,
|
||||
int channel,
|
||||
u16 x, u16 y, u16 w, u16 h,
|
||||
int omap_dsi_update(struct omap_dss_device *dssdev, int channel,
|
||||
void (*callback)(int, void *), void *data);
|
||||
int omap_dsi_request_vc(struct omap_dss_device *dssdev, int *channel);
|
||||
int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue