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:
Linus Torvalds 2012-01-14 15:11:19 -08:00
commit 51be08419d
102 changed files with 6369 additions and 5553 deletions

View 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 &times; 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&nbsp;+&nbsp;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&nbsp;+&nbsp;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&nbsp;+&nbsp;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&nbsp;+&nbsp;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&nbsp;+&nbsp;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&nbsp;+&nbsp;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&nbsp;+&nbsp;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&nbsp;+&nbsp;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>

View File

@ -714,6 +714,7 @@ information.</para>
&sub-nv12m;
&sub-nv12mt;
&sub-nv16;
&sub-nv24;
&sub-m420;
</section>

306
Documentation/fb/api.txt Normal file
View 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.

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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())

View File

@ -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);

View File

@ -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,

View File

@ -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,

View File

@ -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 */

View File

@ -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 */

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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 */

View File

@ -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"

View File

@ -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

View File

@ -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;

View File

@ -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 = {

View File

@ -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;

View File

@ -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

View File

@ -1,6 +0,0 @@
# Display drivers
display-objs := display-sysfs.o
obj-$(CONFIG_DISPLAY_SUPPORT) += display.o

View File

@ -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");

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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}
};

View File

@ -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,

View File

@ -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");

View File

@ -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");

View File

@ -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");

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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/

View File

@ -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,

View File

@ -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 {

View File

@ -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,

View File

@ -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,
},
};

View File

@ -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;
}

View File

@ -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,

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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)
{

View 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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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
};

View File

@ -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 */

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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:

View File

@ -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;
}

View File

@ -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) {

View File

@ -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;
}

View File

@ -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 *

View File

@ -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");

View File

@ -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");

View File

@ -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>");

View File

@ -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");

View File

@ -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");

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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");

View File

@ -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));

View File

@ -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>");

View File

@ -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");

View File

@ -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,

View File

@ -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");

View File

@ -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");

View File

@ -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");

View File

@ -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 "

View File

@ -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");

View File

@ -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

View File

@ -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 {

View File

@ -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 */

View File

@ -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)

View File

@ -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