Commit 9e9ac896 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'fbdev-3.17' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux

Pull fbdev updates from Tomi Valkeinen:
 - much better HDMI infoframe support for OMAP
 - Cirrus Logic CLPS711X framebuffer driver
 - DT support for PL11x CLCD driver
 - various small fixes

* tag 'fbdev-3.17' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux: (35 commits)
  OMAPDSS: DSI: fix depopulating dsi peripherals
  video: hyperv: hyperv_fb: refresh the VM screen by force on VM panic
  video: ARM CLCD: Fix DT-related build problems
  drivers: video: fbdev: atmel_lcdfb.c: Add ability to inverted backlight PWM.
  video: ARM CLCD: Add DT support
  drm/omap: Add infoframe & dvi/hdmi mode support
  OMAPDSS: HDMI: remove the unused code
  OMAPDSS: HDMI5: add support to set infoframe & HDMI mode
  OMAPDSS: HDMI4: add support to set infoframe & HDMI mode
  OMAPDSS: HDMI: add infoframe and hdmi_dvi_mode fields
  OMAPDSS: add hdmi ops to hdmi-connector and tpd12s015
  OMAPDSS: add hdmi ops to hdmi_ops and omap_dss_driver
  OMAPDSS: HDMI: remove custom avi infoframe
  OMAPDSS: HDMI5: use common AVI infoframe support
  OMAPDSS: HDMI4: use common AVI infoframe support
  OMAPDSS: Kconfig: select HDMI
  OMAPDSS: HDMI: fix name conflict
  OMAPDSS: DISPC: clean up dispc_mgr_timings_ok
  OMAPDSS: DISPC: reject interlace for lcd out
  OMAPDSS: DISPC: fix debugfs reg dump
  ...
parents 34b20e6d e4e42b8a
* ARM PrimeCell Color LCD Controller PL110/PL111
See also Documentation/devicetree/bindings/arm/primecell.txt
Required properties:
- compatible: must be one of:
"arm,pl110", "arm,primecell"
"arm,pl111", "arm,primecell"
- reg: base address and size of the control registers block
- interrupt-names: either the single entry "combined" representing a
combined interrupt output (CLCDINTR), or the four entries
"mbe", "vcomp", "lnbu", "fuf" representing the individual
CLCDMBEINTR, CLCDVCOMPINTR, CLCDLNBUINTR, CLCDFUFINTR interrupts
- interrupts: contains an interrupt specifier for each entry in
interrupt-names
- clock-names: should contain "clcdclk" and "apb_pclk"
- clocks: contains phandle and clock specifier pairs for the entries
in the clock-names property. See
Documentation/devicetree/binding/clock/clock-bindings.txt
Optional properties:
- memory-region: phandle to a node describing memory (see
Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt)
to be used for the framebuffer; if not present, the framebuffer
may be located anywhere in the memory
- max-memory-bandwidth: maximum bandwidth in bytes per second that the
cell's memory interface can handle; if not present, the memory
interface is fast enough to handle all possible video modes
Required sub-nodes:
- port: describes LCD panel signals, following the common binding
for video transmitter interfaces; see
Documentation/devicetree/bindings/media/video-interfaces.txt;
when it is a TFT panel, the port's endpoint must define the
following property:
- arm,pl11x,tft-r0g0b0-pads: an array of three 32-bit values,
defining the way CLD pads are wired up; first value
contains index of the "CLD" external pin (pad) used
as R0 (first bit of the red component), second value
index of the pad used as G0, third value index of the
pad used as B0, see also "LCD panel signal multiplexing
details" paragraphs in the PL110/PL111 Technical
Reference Manuals; this implicitly defines available
color modes, for example:
- PL111 TFT 4:4:4 panel:
arm,pl11x,tft-r0g0b0-pads = <4 15 20>;
- PL110 TFT (1:)5:5:5 panel:
arm,pl11x,tft-r0g0b0-pads = <1 7 13>;
- PL111 TFT (1:)5:5:5 panel:
arm,pl11x,tft-r0g0b0-pads = <3 11 19>;
- PL111 TFT 5:6:5 panel:
arm,pl11x,tft-r0g0b0-pads = <3 10 19>;
- PL110 and PL111 TFT 8:8:8 panel:
arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
- PL110 and PL111 TFT 8:8:8 panel, R & B components swapped:
arm,pl11x,tft-r0g0b0-pads = <16 8 0>;
Example:
clcd@10020000 {
compatible = "arm,pl111", "arm,primecell";
reg = <0x10020000 0x1000>;
interrupt-names = "combined";
interrupts = <0 44 4>;
clocks = <&oscclk1>, <&oscclk2>;
clock-names = "clcdclk", "apb_pclk";
max-memory-bandwidth = <94371840>; /* Bps, 1024x768@60 16bpp */
port {
clcd_pads: endpoint {
remote-endpoint = <&clcd_panel>;
arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
};
};
};
panel {
compatible = "panel-dpi";
port {
clcd_panel: endpoint {
remote-endpoint = <&clcd_pads>;
};
};
panel-timing {
clock-frequency = <25175000>;
hactive = <640>;
hback-porch = <40>;
hfront-porch = <24>;
hsync-len = <96>;
vactive = <480>;
vback-porch = <32>;
vfront-porch = <11>;
vsync-len = <2>;
};
};
......@@ -46,6 +46,7 @@ Required properties (as per of_videomode_helper):
Optional properties (as per of_videomode_helper):
- atmel,lcdcon-backlight: enable backlight
- atmel,lcdcon-backlight-inverted: invert backlight PWM polarity
- atmel,lcd-wiring-mode: lcd wiring mode "RGB" or "BRG"
- atmel,power-control-gpio: gpio to power on or off the LCD (as many as needed)
......
* Currus Logic CLPS711X Framebuffer
Required properties:
- compatible: Shall contain "cirrus,clps711x-fb".
- reg : Physical base address and length of the controller's registers +
location and size of the framebuffer memory.
- clocks : phandle + clock specifier pair of the FB reference clock.
- display : phandle to a display node as described in
Documentation/devicetree/bindings/video/display-timing.txt.
Additionally, the display node has to define properties:
- bits-per-pixel: Bits per pixel.
- ac-prescale : LCD AC bias frequency. This frequency is the required
AC bias frequency for a given manufacturer's LCD plate.
- cmap-invert : Invert the color levels (Optional).
Optional properties:
- lcd-supply: Regulator for LCD supply voltage.
Example:
fb: fb@800002c0 {
compatible = "cirrus,ep7312-fb", "cirrus,clps711x-fb";
reg = <0x800002c0 0xd44>, <0x60000000 0xc000>;
clocks = <&clks 2>;
lcd-supply = <&reg5v0>;
display = <&display>;
};
display: display {
model = "320x240x4";
native-mode = <&timing0>;
bits-per-pixel = <4>;
ac-prescale = <17>;
display-timings {
timing0: 320x240 {
hactive = <320>;
hback-porch = <0>;
hfront-porch = <0>;
hsync-len = <0>;
vactive = <240>;
vback-porch = <0>;
vfront-porch = <0>;
vsync-len = <0>;
clock-frequency = <6500000>;
};
};
};
......@@ -606,7 +606,7 @@ W: http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_
S: Supported
F: drivers/char/hw_random/geode-rng.c
F: drivers/crypto/geode*
F: drivers/video/geode/
F: drivers/video/fbdev/geode/
F: arch/x86/include/asm/geode.h
AMD IOMMU (AMD-VI)
......@@ -735,8 +735,8 @@ F: drivers/ata/pata_arasan_cf.c
ARC FRAMEBUFFER DRIVER
M: Jaya Kumar <jayalk@intworks.biz>
S: Maintained
F: drivers/video/arcfb.c
F: drivers/video/fb_defio.c
F: drivers/video/fbdev/arcfb.c
F: drivers/video/fbdev/core/fb_defio.c
ARM MFM AND FLOPPY DRIVERS
M: Ian Molton <spyro@f2s.com>
......@@ -775,7 +775,7 @@ F: sound/arm/aaci.*
ARM PRIMECELL CLCD PL110 DRIVER
M: Russell King <linux@arm.linux.org.uk>
S: Maintained
F: drivers/video/amba-clcd.*
F: drivers/video/fbdev/amba-clcd.*
ARM PRIMECELL KMI PL050 DRIVER
M: Russell King <linux@arm.linux.org.uk>
......@@ -1180,7 +1180,7 @@ M: Daniel Walker <dwalker@fifo99.com>
M: Bryan Huntsman <bryanh@codeaurora.org>
L: linux-arm-msm@vger.kernel.org
F: arch/arm/mach-msm/
F: drivers/video/msm/
F: drivers/video/fbdev/msm/
F: drivers/mmc/host/msm_sdcc.c
F: drivers/mmc/host/msm_sdcc.h
F: drivers/tty/serial/msm_serial.h
......@@ -1414,7 +1414,7 @@ F: drivers/mtd/nand/nuc900_nand.c
F: drivers/rtc/rtc-nuc900.c
F: drivers/spi/spi-nuc900.c
F: drivers/usb/host/ehci-w90x900.c
F: drivers/video/nuc900fb.c
F: drivers/video/fbdev/nuc900fb.c
ARM/U300 MACHINE SUPPORT
M: Linus Walleij <linus.walleij@linaro.org>
......@@ -1484,9 +1484,9 @@ F: drivers/rtc/rtc-vt8500.c
F: drivers/tty/serial/vt8500_serial.c
F: drivers/usb/host/ehci-platform.c
F: drivers/usb/host/uhci-platform.c
F: drivers/video/vt8500lcdfb.*
F: drivers/video/wm8505fb*
F: drivers/video/wmt_ge_rops.*
F: drivers/video/fbdev/vt8500lcdfb.*
F: drivers/video/fbdev/wm8505fb*
F: drivers/video/fbdev/wmt_ge_rops.*
ARM/ZIPIT Z2 SUPPORT
M: Marek Vasut <marek.vasut@gmail.com>
......@@ -1676,7 +1676,7 @@ ATMEL LCDFB DRIVER
M: Nicolas Ferre <nicolas.ferre@atmel.com>
L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/video/atmel_lcdfb.c
F: drivers/video/fbdev/atmel_lcdfb.c
F: include/video/atmel_lcdc.h
ATMEL MACB ETHERNET DRIVER
......@@ -2703,7 +2703,7 @@ M: Russell King <linux@arm.linux.org.uk>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
W: http://www.arm.linux.org.uk/
S: Maintained
F: drivers/video/cyber2000fb.*
F: drivers/video/fbdev/cyber2000fb.*
CYCLADES ASYNC MUX DRIVER
W: http://www.cyclades.com/
......@@ -2941,7 +2941,7 @@ M: Bernie Thompson <bernie@plugable.com>
L: linux-fbdev@vger.kernel.org
S: Maintained
W: http://plugable.com/category/projects/udlfb/
F: drivers/video/udlfb.c
F: drivers/video/fbdev/udlfb.c
F: include/video/udlfb.h
F: Documentation/fb/udlfb.txt
......@@ -3452,7 +3452,7 @@ EFIFB FRAMEBUFFER DRIVER
L: linux-fbdev@vger.kernel.org
M: Peter Jones <pjones@redhat.com>
S: Maintained
F: drivers/video/efifb.c
F: drivers/video/fbdev/efifb.c
EFS FILESYSTEM
W: http://aeschi.ch.eu.org/efs/
......@@ -3517,7 +3517,7 @@ EPSON S1D13XXX FRAMEBUFFER DRIVER
M: Kristoffer Ericson <kristoffer.ericson@gmail.com>
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git
F: drivers/video/s1d13xxxfb.c
F: drivers/video/fbdev/s1d13xxxfb.c
F: include/video/s1d13xxxfb.h
ETHERNET BRIDGE
......@@ -3595,7 +3595,7 @@ M: Donghwa Lee <dh09.lee@samsung.com>
M: Kyungmin Park <kyungmin.park@samsung.com>
L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/video/exynos/exynos_mipi*
F: drivers/video/fbdev/exynos/exynos_mipi*
F: include/video/exynos_mipi*
F71805F HARDWARE MONITORING DRIVER
......@@ -3774,7 +3774,7 @@ FREESCALE DIU FRAMEBUFFER DRIVER
M: Timur Tabi <timur@tabi.org>
L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/video/fsl-diu-fb.*
F: drivers/video/fbdev/fsl-diu-fb.*
FREESCALE DMA DRIVER
M: Li Yang <leoli@freescale.com>
......@@ -3796,7 +3796,7 @@ L: linux-fbdev@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: include/linux/platform_data/video-imxfb.h
F: drivers/video/imxfb.c
F: drivers/video/fbdev/imxfb.c
FREESCALE SOC FS_ENET DRIVER
M: Pantelis Antoniou <pantelis.antoniou@gmail.com>
......@@ -4222,7 +4222,7 @@ M: Ferenc Bakonyi <fero@drama.obuda.kando.hu>
L: linux-nvidia@lists.surfsouth.com
W: http://drama.obuda.kando.hu/~fero/cgi-bin/hgafb.shtml
S: Maintained
F: drivers/video/hgafb.c
F: drivers/video/fbdev/hgafb.c
HIBERNATION (aka Software Suspend, aka swsusp)
M: "Rafael J. Wysocki" <rjw@rjwysocki.net>
......@@ -4364,7 +4364,7 @@ F: drivers/hv/
F: drivers/input/serio/hyperv-keyboard.c
F: drivers/net/hyperv/
F: drivers/scsi/storvsc_drv.c
F: drivers/video/hyperv_fb.c
F: drivers/video/fbdev/hyperv_fb.c
F: include/linux/hyperv.h
F: tools/hv/
......@@ -4620,7 +4620,7 @@ F: security/integrity/ima/
IMS TWINTURBO FRAMEBUFFER DRIVER
L: linux-fbdev@vger.kernel.org
S: Orphan
F: drivers/video/imsttfb.c
F: drivers/video/fbdev/imsttfb.c
INFINIBAND SUBSYSTEM
M: Roland Dreier <roland@kernel.org>
......@@ -4687,13 +4687,13 @@ M: Maik Broemme <mbroemme@plusserver.de>
L: linux-fbdev@vger.kernel.org
S: Maintained
F: Documentation/fb/intelfb.txt
F: drivers/video/intelfb/
F: drivers/video/fbdev/intelfb/
INTEL 810/815 FRAMEBUFFER DRIVER
M: Antonino Daplas <adaplas@gmail.com>
L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/video/i810/
F: drivers/video/fbdev/i810/
INTEL MENLOW THERMAL DRIVER
M: Sujith Thomas <sujith.thomas@intel.com>
......@@ -5758,7 +5758,7 @@ F: drivers/mmc/host/mvsdio.*
MATROX FRAMEBUFFER DRIVER
L: linux-fbdev@vger.kernel.org
S: Orphan
F: drivers/video/matrox/matroxfb_*
F: drivers/video/fbdev/matrox/matroxfb_*
F: include/uapi/linux/matroxfb.h
MAX16065 HARDWARE MONITOR DRIVER
......@@ -6398,8 +6398,8 @@ NVIDIA (rivafb and nvidiafb) FRAMEBUFFER DRIVER
M: Antonino Daplas <adaplas@gmail.com>
L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/video/riva/
F: drivers/video/nvidia/
F: drivers/video/fbdev/riva/
F: drivers/video/fbdev/nvidia/
NVM EXPRESS DRIVER
M: Matthew Wilcox <willy@linux.intel.com>
......@@ -6469,14 +6469,14 @@ M: Tomi Valkeinen <tomi.valkeinen@ti.com>
L: linux-fbdev@vger.kernel.org
L: linux-omap@vger.kernel.org
S: Maintained
F: drivers/video/omap/
F: drivers/video/fbdev/omap/
OMAP DISPLAY SUBSYSTEM and FRAMEBUFFER SUPPORT (DSS2)
M: Tomi Valkeinen <tomi.valkeinen@ti.com>
L: linux-omap@vger.kernel.org
L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/video/omap2/
F: drivers/video/fbdev/omap2/
F: Documentation/arm/OMAP/DSS
OMAP HARDWARE SPINLOCK SUPPORT
......@@ -6768,7 +6768,7 @@ F: drivers/char/agp/parisc-agp.c
F: drivers/input/serio/gscps2.c
F: drivers/parport/parport_gsc.*
F: drivers/tty/serial/8250/8250_gsc.c
F: drivers/video/sti*
F: drivers/video/fbdev/sti*
F: drivers/video/console/sti*
F: drivers/video/logo/logo_parisc*
......@@ -7027,7 +7027,7 @@ S: Maintained
T: git git://github.com/gxt/linux.git
F: drivers/input/serio/i8042-unicore32io.h
F: drivers/i2c/busses/i2c-puv3.c
F: drivers/video/fb-puv3.c
F: drivers/video/fbdev/fb-puv3.c
F: drivers/rtc/rtc-puv3.c
PMBUS HARDWARE MONITORING DRIVERS
......@@ -7407,7 +7407,7 @@ RADEON FRAMEBUFFER DISPLAY DRIVER
M: Benjamin Herrenschmidt <benh@kernel.crashing.org>
L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/video/aty/radeon*
F: drivers/video/fbdev/aty/radeon*
F: include/uapi/linux/radeonfb.h
RADIOSHARK RADIO DRIVER
......@@ -7429,7 +7429,7 @@ RAGE128 FRAMEBUFFER DISPLAY DRIVER
M: Paul Mackerras <paulus@samba.org>
L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/video/aty/aty128fb.c
F: drivers/video/fbdev/aty/aty128fb.c
RALINK RT2X00 WIRELESS LAN DRIVER
P: rt2x00 project
......@@ -7677,7 +7677,7 @@ S3 SAVAGE FRAMEBUFFER DRIVER
M: Antonino Daplas <adaplas@gmail.com>
L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/video/savage/
F: drivers/video/fbdev/savage/
S390
M: Martin Schwidefsky <schwidefsky@de.ibm.com>
......@@ -7800,7 +7800,7 @@ SAMSUNG FRAMEBUFFER DRIVER
M: Jingoo Han <jg1.han@samsung.com>
L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/video/s3c-fb.c
F: drivers/video/fbdev/s3c-fb.c
SAMSUNG MULTIFUNCTION DEVICE DRIVERS
M: Sangbeom Kim <sbkim73@samsung.com>
......@@ -8297,7 +8297,7 @@ M: Thomas Winischhofer <thomas@winischhofer.net>
W: http://www.winischhofer.net/linuxsisvga.shtml
S: Maintained
F: Documentation/fb/sisfb.txt
F: drivers/video/sis/
F: drivers/video/fbdev/sis/
F: include/video/sisfb.h
SIS USB2VGA DRIVER
......@@ -8406,7 +8406,7 @@ SMSC UFX6000 and UFX7000 USB to VGA DRIVER
M: Steve Glendinning <steve.glendinning@shawell.net>
L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/video/smscufx.c
F: drivers/video/fbdev/smscufx.c
SOC-CAMERA V4L2 SUBSYSTEM
M: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
......@@ -9670,7 +9670,7 @@ L: linux-fbdev@vger.kernel.org
W: http://dev.gentoo.org/~spock/projects/uvesafb/
S: Maintained
F: Documentation/fb/uvesafb.txt
F: drivers/video/uvesafb.*
F: drivers/video/fbdev/uvesafb.*
VFAT/FAT/MSDOS FILESYSTEM
M: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
......@@ -9743,7 +9743,7 @@ S: Maintained
F: include/linux/via-core.h
F: include/linux/via-gpio.h
F: include/linux/via_i2c.h
F: drivers/video/via/
F: drivers/video/fbdev/via/
VIA VELOCITY NETWORK DRIVER
M: Francois Romieu <romieu@fr.zoreil.com>
......
......@@ -32,8 +32,16 @@ struct omap_connector {
struct drm_connector base;
struct omap_dss_device *dssdev;
struct drm_encoder *encoder;
bool hdmi_mode;
};
bool omap_connector_get_hdmi_mode(struct drm_connector *connector)
{
struct omap_connector *omap_connector = to_omap_connector(connector);
return omap_connector->hdmi_mode;
}
void copy_timings_omap_to_drm(struct drm_display_mode *mode,
struct omap_video_timings *timings)
{
......@@ -162,10 +170,14 @@ static int omap_connector_get_modes(struct drm_connector *connector)
drm_mode_connector_update_edid_property(
connector, edid);
n = drm_add_edid_modes(connector, edid);
omap_connector->hdmi_mode =
drm_detect_hdmi_monitor(edid);
} else {
drm_mode_connector_update_edid_property(
connector, NULL);
}
kfree(edid);
} else {
struct drm_display_mode *mode = drm_mode_create(dev);
......
......@@ -187,6 +187,7 @@ struct drm_encoder *omap_connector_attached_encoder(
struct drm_connector *connector);
void omap_connector_flush(struct drm_connector *connector,
int x, int y, int w, int h);
bool omap_connector_get_hdmi_mode(struct drm_connector *connector);
void copy_timings_omap_to_drm(struct drm_display_mode *mode,
struct omap_video_timings *timings);
......
......@@ -17,6 +17,8 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <drm/drm_edid.h>
#include "omap_drv.h"
#include "drm_crtc.h"
......@@ -89,6 +91,31 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = encoder->dev;
struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
struct omap_dss_device *dssdev = omap_encoder->dssdev;
struct drm_connector *connector;
bool hdmi_mode;
int r;
hdmi_mode = false;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
if (connector->encoder == encoder) {
hdmi_mode = omap_connector_get_hdmi_mode(connector);
break;
}
}
if (dssdev->driver->set_hdmi_mode)
dssdev->driver->set_hdmi_mode(dssdev, hdmi_mode);
if (hdmi_mode && dssdev->driver->set_hdmi_infoframe) {
struct hdmi_avi_infoframe avi;
r = drm_hdmi_avi_infoframe_from_display_mode(&avi, adjusted_mode);
if (r == 0)
dssdev->driver->set_hdmi_infoframe(dssdev, &avi);
}
}
static void omap_encoder_prepare(struct drm_encoder *encoder)
......
......@@ -49,12 +49,6 @@
#error wrong architecture for the MC68x328 frame buffer device
#endif
#if defined(CONFIG_FB_68328_INVERT)
#define MC68X328FB_MONO_VISUAL FB_VISUAL_MONO01
#else
#define MC68X328FB_MONO_VISUAL FB_VISUAL_MONO10
#endif
static u_long videomemory;
static u_long videomemorysize;
......@@ -462,7 +456,7 @@ int __init mc68x328fb_init(void)
fb_info.fix.line_length =
get_line_length(mc68x328fb_default.xres_virtual, mc68x328fb_default.bits_per_pixel);
fb_info.fix.visual = (mc68x328fb_default.bits_per_pixel) == 1 ?
MC68X328FB_MONO_VISUAL : FB_VISUAL_PSEUDOCOLOR;
FB_VISUAL_MONO10 : FB_VISUAL_PSEUDOCOLOR;
if (fb_info.var.bits_per_pixel == 1) {
fb_info.var.red.length = fb_info.var.green.length = fb_info.var.blue.length = 1;
fb_info.var.red.offset = fb_info.var.green.offset = fb_info.var.blue.offset = 0;
......
......@@ -280,6 +280,8 @@ config FB_ARMCLCD
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select FB_MODE_HELPERS if OF
select VIDEOMODE_HELPERS if OF
help
This framebuffer device driver is for the ARM PrimeCell PL110
Colour LCD controller. ARM PrimeCells provide the building
......@@ -307,15 +309,26 @@ config FB_ACORN
hardware found in Acorn RISC PCs and other ARM-based machines. If
unsure, say N.
config FB_CLPS711X
bool "CLPS711X LCD support"
depends on (FB = y) && ARM && ARCH_CLPS711X
config FB_CLPS711X_OLD
tristate
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
config FB_CLPS711X
tristate "CLPS711X LCD support"
depends on FB && (ARCH_CLPS711X || COMPILE_TEST)
select FB_CLPS711X_OLD if ARCH_CLPS711X && !ARCH_MULTIPLATFORM
select BACKLIGHT_LCD_SUPPORT
select FB_MODE_HELPERS
select FB_SYS_FILLRECT
select FB_SYS_COPYAREA
select FB_SYS_IMAGEBLIT
select LCD_CLASS_DEVICE
select VIDEOMODE_HELPERS
help
Say Y to enable the Framebuffer driver for the CLPS7111 and
EP7212 processors.
Say Y to enable the Framebuffer driver for the Cirrus Logic
CLPS711X CPUs.
config FB_SA1100
bool "SA-1100 LCD support"
......
......@@ -14,7 +14,8 @@ obj-$(CONFIG_FB_WMT_GE_ROPS) += wmt_ge_rops.o
# Hardware specific drivers go first
obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o
obj-$(CONFIG_FB_ARC) += arcfb.o
obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o
obj-$(CONFIG_FB_CLPS711X) += clps711x-fb.o
obj-$(CONFIG_FB_CLPS711X_OLD) += clps711xfb.o
obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o
obj-$(CONFIG_FB_GRVGA) += grvga.o
obj-$(CONFIG_FB_PM2) += pm2fb.o
......
......@@ -26,6 +26,13 @@
#include <linux/amba/clcd.h>
#include <linux/clk.h>
#include <linux/hardirq.h>
#include <linux/dma-mapping.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_graph.h>
#include <video/display_timing.h>
#include <video/of_display_timing.h>
#include <video/videomode.h>
#include <asm/sizes.h>
......@@ -543,12 +550,268 @@ static int clcdfb_register(struct clcd_fb *fb)
return ret;
}
#ifdef CONFIG_OF
static int clcdfb_of_get_dpi_panel_mode(struct device_node *node,
struct fb_videomode *mode)
{
int err;
struct display_timing timing;
struct videomode video;
err = of_get_display_timing(node, "panel-timing", &timing);
if (err)
return err;
videomode_from_timing(&timing, &video);
err = fb_videomode_from_videomode(&video, mode);
if (err)
return err;
return 0;
}
static int clcdfb_snprintf_mode(char *buf, int size, struct fb_videomode *mode)
{
return snprintf(buf, size, "%ux%u@%u", mode->xres, mode->yres,
mode->refresh);
}
static int clcdfb_of_get_mode(struct device *dev, struct device_node *endpoint,
struct fb_videomode *mode)
{
int err;
struct device_node *panel;
char *name;
int len;
panel = of_graph_get_remote_port_parent(endpoint);
if (!panel)
return -ENODEV;
/* Only directly connected DPI panels supported for now */
if (of_device_is_compatible(panel, "panel-dpi"))
err = clcdfb_of_get_dpi_panel_mode(panel, mode);
else
err = -ENOENT;
if (err)
return err;
len = clcdfb_snprintf_mode(NULL, 0, mode);
name = devm_kzalloc(dev, len + 1, GFP_KERNEL);
clcdfb_snprintf_mode(name, len + 1, mode);
mode->name = name;
return 0;
}
static int clcdfb_of_init_tft_panel(struct clcd_fb *fb, u32 r0, u32 g0, u32 b0)
{
static struct {
unsigned int part;
u32 r0, g0, b0;
u32 caps;
} panels[] = {
{ 0x110, 1, 7, 13, CLCD_CAP_5551 },
{ 0x110, 0, 8, 16, CLCD_CAP_888 },
{ 0x111, 4, 14, 20, CLCD_CAP_444 },
{ 0x111, 3, 11, 19, CLCD_CAP_444 | CLCD_CAP_5551 },
{ 0x111, 3, 10, 19, CLCD_CAP_444 | CLCD_CAP_5551 |
CLCD_CAP_565 },
{ 0x111, 0, 8, 16, CLCD_CAP_444 | CLCD_CAP_5551 |
CLCD_CAP_565 | CLCD_CAP_888 },
};
int i;
/* Bypass pixel clock divider, data output on the falling edge */
fb->panel->tim2 = TIM2_BCD | TIM2_IPC;
/* TFT display, vert. comp. interrupt at the start of the back porch */
fb->panel->cntl |= CNTL_LCDTFT | CNTL_LCDVCOMP(1);
fb->panel->caps = 0;
/* Match the setup with known variants */
for (i = 0; i < ARRAY_SIZE(panels) && !fb->panel->caps; i++) {
if (amba_part(fb->dev) != panels[i].part)
continue;
if (g0 != panels[i].g0)
continue;
if (r0 == panels[i].r0 && b0 == panels[i].b0)
fb->panel->caps = panels[i].caps & CLCD_CAP_RGB;
if (r0 == panels[i].b0 && b0 == panels[i].r0)
fb->panel->caps = panels[i].caps & CLCD_CAP_BGR;
}
return fb->panel->caps ? 0 : -EINVAL;
}
static int clcdfb_of_init_display(struct clcd_fb *fb)
{
struct device_node *endpoint;
int err;
u32 max_bandwidth;
u32 tft_r0b0g0[3];
fb->panel = devm_kzalloc(&fb->dev->dev, sizeof(*fb->panel), GFP_KERNEL);
if (!fb->panel)
return -ENOMEM;
endpoint = of_graph_get_next_endpoint(fb->dev->dev.of_node, NULL);
if (!endpoint)
return -ENODEV;
err = clcdfb_of_get_mode(&fb->dev->dev, endpoint, &fb->panel->mode);
if (err)
return err;
err = of_property_read_u32(fb->dev->dev.of_node, "max-memory-bandwidth",
&max_bandwidth);
if (!err)
fb->panel->bpp = 8 * max_bandwidth / (fb->panel->mode.xres *
fb->panel->mode.yres * fb->panel->mode.refresh);
else
fb->panel->bpp = 32;
#ifdef CONFIG_CPU_BIG_ENDIAN
fb->panel->cntl |= CNTL_BEBO;
#endif
fb->panel->width = -1;
fb->panel->height = -1;
if (of_property_read_u32_array(endpoint,
"arm,pl11x,tft-r0g0b0-pads",
tft_r0b0g0, ARRAY_SIZE(tft_r0b0g0)) == 0)
return clcdfb_of_init_tft_panel(fb, tft_r0b0g0[0],
tft_r0b0g0[1], tft_r0b0g0[2]);
return -ENOENT;
}
static int clcdfb_of_vram_setup(struct clcd_fb *fb)
{
int err;
struct device_node *memory;
u64 size;
err = clcdfb_of_init_display(fb);
if (err)
return err;
memory = of_parse_phandle(fb->dev->dev.of_node, "memory-region", 0);
if (!memory)
return -ENODEV;
fb->fb.screen_base = of_iomap(memory, 0);
if (!fb->fb.screen_base)
return -ENOMEM;
fb->fb.fix.smem_start = of_translate_address(memory,
of_get_address(memory, 0, &size, NULL));
fb->fb.fix.smem_len = size;
return 0;
}
static int clcdfb_of_vram_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
{
unsigned long off, user_size, kernel_size;
off = vma->vm_pgoff << PAGE_SHIFT;
user_size = vma->vm_end - vma->vm_start;
kernel_size = fb->fb.fix.smem_len;
if (off >= kernel_size || user_size > (kernel_size - off))
return -ENXIO;
return remap_pfn_range(vma, vma->vm_start,
__phys_to_pfn(fb->fb.fix.smem_start) + vma->vm_pgoff,
user_size,
pgprot_writecombine(vma->vm_page_prot));
}
static void clcdfb_of_vram_remove(struct clcd_fb *fb)
{
iounmap(fb->fb.screen_base);
}
static int clcdfb_of_dma_setup(struct clcd_fb *fb)
{
unsigned long framesize;
dma_addr_t dma;
int err;
err = clcdfb_of_init_display(fb);
if (err)
return err;
framesize = fb->panel->mode.xres * fb->panel->mode.yres *
fb->panel->bpp / 8;
fb->fb.screen_base = dma_alloc_coherent(&fb->dev->dev, framesize,
&dma, GFP_KERNEL);
if (!fb->fb.screen_base)
return -ENOMEM;
fb->fb.fix.smem_start = dma;
fb->fb.fix.smem_len = framesize;
return 0;
}
static int clcdfb_of_dma_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
{
return dma_mmap_writecombine(&fb->dev->dev, vma, fb->fb.screen_base,
fb->fb.fix.smem_start, fb->fb.fix.smem_len);
}
static void clcdfb_of_dma_remove(struct clcd_fb *fb)
{
dma_free_coherent(&fb->dev->dev, fb->fb.fix.smem_len,
fb->fb.screen_base, fb->fb.fix.smem_start);
}
static struct clcd_board *clcdfb_of_get_board(struct amba_device *dev)
{
struct clcd_board *board = devm_kzalloc(&dev->dev, sizeof(*board),
GFP_KERNEL);
struct device_node *node = dev->dev.of_node;
if (!board)
return NULL;
board->name = of_node_full_name(node);
board->caps = CLCD_CAP_ALL;
board->check = clcdfb_check;
board->decode = clcdfb_decode;
if (of_find_property(node, "memory-region", NULL)) {
board->setup = clcdfb_of_vram_setup;
board->mmap = clcdfb_of_vram_mmap;
board->remove = clcdfb_of_vram_remove;
} else {
board->setup = clcdfb_of_dma_setup;
board->mmap = clcdfb_of_dma_mmap;
board->remove = clcdfb_of_dma_remove;
}
return board;
}
#else
static struct clcd_board *clcdfb_of_get_board(struct amba_device *dev)
{
return NULL;
}
#endif
static int clcdfb_probe(struct amba_device *dev, const struct amba_id *id)
{
struct clcd_board *board = dev_get_platdata(&dev->dev);
struct clcd_fb *fb;
int ret;
if (!board)
board = clcdfb_of_get_board(dev);
if (!board)
return -EINVAL;
......
......@@ -1097,6 +1097,7 @@ static int atmel_lcdfb_of_init(struct atmel_lcdfb_info *sinfo)
pdata->lcd_wiring_mode = ret;
pdata->lcdcon_is_backlight = of_property_read_bool(display_np, "atmel,lcdcon-backlight");
pdata->lcdcon_pol_negative = of_property_read_bool(display_np, "atmel,lcdcon-backlight-inverted");
timings = of_get_display_timings(display_np);
if (!timings) {
......
/*
* Cirrus Logic CLPS711X FB driver
*
* Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru>
* Based on driver by Russell King <rmk@arm.linux.org.uk>
*
* 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.
*/
#include <linux/clk.h>
#include <linux/fb.h>
#include <linux/io.h>
#include <linux/lcd.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#include <linux/mfd/syscon/clps711x.h>
#include <linux/regulator/consumer.h>
#include <video/of_display_timing.h>
#define CLPS711X_FB_NAME "clps711x-fb"
#define CLPS711X_FB_BPP_MAX (4)
/* Registers relative to LCDCON */
#define CLPS711X_LCDCON (0x0000)
# define LCDCON_GSEN BIT(30)
# define LCDCON_GSMD BIT(31)
#define CLPS711X_PALLSW (0x0280)
#define CLPS711X_PALMSW (0x02c0)
#define CLPS711X_FBADDR (0x0d40)
struct clps711x_fb_info {
struct clk *clk;
void __iomem *base;
struct regmap *syscon;
resource_size_t buffsize;
struct fb_videomode mode;
struct regulator *lcd_pwr;
u32 ac_prescale;
bool cmap_invert;
};
static int clps711x_fb_setcolreg(u_int regno, u_int red, u_int green,
u_int blue, u_int transp, struct fb_info *info)
{
struct clps711x_fb_info *cfb = info->par;
u32 level, mask, shift;
if (regno >= BIT(info->var.bits_per_pixel))
return -EINVAL;
shift = 4 * (regno & 7);
mask = 0xf << shift;
/* gray = 0.30*R + 0.58*G + 0.11*B */
level = (((red * 77 + green * 151 + blue * 28) >> 20) << shift) & mask;
if (cfb->cmap_invert)
level = 0xf - level;
regno = (regno < 8) ? CLPS711X_PALLSW : CLPS711X_PALMSW;
writel((readl(cfb->base + regno) & ~mask) | level, cfb->base + regno);
return 0;
}
static int clps711x_fb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
u32 val;
if (var->bits_per_pixel < 1 ||
var->bits_per_pixel > CLPS711X_FB_BPP_MAX)
return -EINVAL;
if (!var->pixclock)
return -EINVAL;
val = DIV_ROUND_UP(var->xres, 16) - 1;
if (val < 0x01 || val > 0x3f)
return -EINVAL;
val = DIV_ROUND_UP(var->yres * var->xres * var->bits_per_pixel, 128);
val--;
if (val < 0x001 || val > 0x1fff)
return -EINVAL;
var->transp.msb_right = 0;
var->transp.offset = 0;
var->transp.length = 0;
var->red.msb_right = 0;
var->red.offset = 0;
var->red.length = var->bits_per_pixel;
var->green = var->red;
var->blue = var->red;
var->grayscale = var->bits_per_pixel > 1;
return 0;
}
static int clps711x_fb_set_par(struct fb_info *info)
{
struct clps711x_fb_info *cfb = info->par;
resource_size_t size;
u32 lcdcon, pps;
size = (info->var.xres * info->var.yres * info->var.bits_per_pixel) / 8;
if (size > cfb->buffsize)
return -EINVAL;
switch (info->var.bits_per_pixel) {
case 1:
info->fix.visual = FB_VISUAL_MONO01;
break;
case 2:
case 4:
info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
break;
default:
return -EINVAL;
}
info->fix.line_length = info->var.xres * info->var.bits_per_pixel / 8;
info->fix.smem_len = size;
lcdcon = (info->var.xres * info->var.yres *
info->var.bits_per_pixel) / 128 - 1;
lcdcon |= ((info->var.xres / 16) - 1) << 13;
lcdcon |= (cfb->ac_prescale & 0x1f) << 25;
pps = clk_get_rate(cfb->clk) / (PICOS2KHZ(info->var.pixclock) * 1000);
if (pps)
pps--;
lcdcon |= (pps & 0x3f) << 19;
if (info->var.bits_per_pixel == 4)
lcdcon |= LCDCON_GSMD;
if (info->var.bits_per_pixel >= 2)
lcdcon |= LCDCON_GSEN;
/* LCDCON must only be changed while the LCD is disabled */
regmap_update_bits(cfb->syscon, SYSCON_OFFSET, SYSCON1_LCDEN, 0);
writel(lcdcon, cfb->base + CLPS711X_LCDCON);
regmap_update_bits(cfb->syscon, SYSCON_OFFSET,
SYSCON1_LCDEN, SYSCON1_LCDEN);
return 0;
}
static int clps711x_fb_blank(int blank, struct fb_info *info)
{
/* Return happy */
return 0;
}
static struct fb_ops clps711x_fb_ops = {
.owner = THIS_MODULE,
.fb_setcolreg = clps711x_fb_setcolreg,
.fb_check_var = clps711x_fb_check_var,
.fb_set_par = clps711x_fb_set_par,
.fb_blank = clps711x_fb_blank,
.fb_fillrect = sys_fillrect,
.fb_copyarea = sys_copyarea,
.fb_imageblit = sys_imageblit,
};
static int clps711x_lcd_check_fb(struct lcd_device *lcddev, struct fb_info *fi)
{
struct clps711x_fb_info *cfb = dev_get_drvdata(&lcddev->dev);
return (!fi || fi->par == cfb) ? 1 : 0;
}
static int clps711x_lcd_get_power(struct lcd_device *lcddev)
{
struct clps711x_fb_info *cfb = dev_get_drvdata(&lcddev->dev);
if (!IS_ERR_OR_NULL(cfb->lcd_pwr))
if (!regulator_is_enabled(cfb->lcd_pwr))
return FB_BLANK_NORMAL;
return FB_BLANK_UNBLANK;
}
static int clps711x_lcd_set_power(struct lcd_device *lcddev, int blank)
{
struct clps711x_fb_info *cfb = dev_get_drvdata(&lcddev->dev);
if (!IS_ERR_OR_NULL(cfb->lcd_pwr)) {
if (blank == FB_BLANK_UNBLANK) {
if (!regulator_is_enabled(cfb->lcd_pwr))
return regulator_enable(cfb->lcd_pwr);
} else {
if (regulator_is_enabled(cfb->lcd_pwr))
return regulator_disable(cfb->lcd_pwr);
}
}
return 0;
}
static struct lcd_ops clps711x_lcd_ops = {
.check_fb = clps711x_lcd_check_fb,
.get_power = clps711x_lcd_get_power,
.set_power = clps711x_lcd_set_power,
};
static int clps711x_fb_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *disp, *np = dev->of_node;
struct clps711x_fb_info *cfb;
struct lcd_device *lcd;
struct fb_info *info;
struct resource *res;
int ret = -ENOENT;
u32 val;
if (fb_get_options(CLPS711X_FB_NAME, NULL))
return -ENODEV;
info = framebuffer_alloc(sizeof(*cfb), dev);
if (!info)
return -ENOMEM;
cfb = info->par;
platform_set_drvdata(pdev, info);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
goto out_fb_release;
cfb->base = devm_ioremap(dev, res->start, resource_size(res));
if (!cfb->base) {
ret = -ENOMEM;
goto out_fb_release;
}
info->fix.mmio_start = res->start;
info->fix.mmio_len = resource_size(res);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
info->screen_base = devm_ioremap_resource(dev, res);
if (IS_ERR(info->screen_base)) {
ret = PTR_ERR(info->screen_base);
goto out_fb_release;
}
/* Physical address should be aligned to 256 MiB */
if (res->start & 0x0fffffff) {
ret = -EINVAL;
goto out_fb_release;
}
info->apertures = alloc_apertures(1);
if (!info->apertures) {
ret = -ENOMEM;
goto out_fb_release;
}
cfb->buffsize = resource_size(res);
info->fix.smem_start = res->start;
info->apertures->ranges[0].base = info->fix.smem_start;
info->apertures->ranges[0].size = cfb->buffsize;
cfb->clk = devm_clk_get(dev, NULL);
if (IS_ERR(cfb->clk)) {
ret = PTR_ERR(cfb->clk);
goto out_fb_release;
}
cfb->syscon =
syscon_regmap_lookup_by_compatible("cirrus,clps711x-syscon1");
if (IS_ERR(cfb->syscon)) {
ret = PTR_ERR(cfb->syscon);
goto out_fb_release;
}
disp = of_parse_phandle(np, "display", 0);
if (!disp) {
dev_err(&pdev->dev, "No display defined\n");
ret = -ENODATA;
goto out_fb_release;
}
ret = of_get_fb_videomode(disp, &cfb->mode, OF_USE_NATIVE_MODE);
if (ret)
goto out_fb_release;
of_property_read_u32(disp, "ac-prescale", &cfb->ac_prescale);
cfb->cmap_invert = of_property_read_bool(disp, "cmap-invert");
ret = of_property_read_u32(disp, "bits-per-pixel",
&info->var.bits_per_pixel);
if (ret)
goto out_fb_release;
/* Force disable LCD on any mismatch */
if (info->fix.smem_start != (readb(cfb->base + CLPS711X_FBADDR) << 28))
regmap_update_bits(cfb->syscon, SYSCON_OFFSET,
SYSCON1_LCDEN, 0);
ret = regmap_read(cfb->syscon, SYSCON_OFFSET, &val);
if (ret)
goto out_fb_release;
if (!(val & SYSCON1_LCDEN)) {
/* Setup start FB address */
writeb(info->fix.smem_start >> 28, cfb->base + CLPS711X_FBADDR);
/* Clean FB memory */
memset_io(info->screen_base, 0, cfb->buffsize);
}
cfb->lcd_pwr = devm_regulator_get(dev, "lcd");
if (PTR_ERR(cfb->lcd_pwr) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
goto out_fb_release;
}
info->fbops = &clps711x_fb_ops;
info->flags = FBINFO_DEFAULT;
info->var.activate = FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW;
info->var.height = -1;
info->var.width = -1;
info->var.vmode = FB_VMODE_NONINTERLACED;
info->fix.type = FB_TYPE_PACKED_PIXELS;
info->fix.accel = FB_ACCEL_NONE;
strlcpy(info->fix.id, CLPS711X_FB_NAME, sizeof(info->fix.id));
fb_videomode_to_var(&info->var, &cfb->mode);
ret = fb_alloc_cmap(&info->cmap, BIT(CLPS711X_FB_BPP_MAX), 0);
if (ret)
goto out_fb_release;
ret = fb_set_var(info, &info->var);
if (ret)
goto out_fb_dealloc_cmap;
ret = register_framebuffer(info);
if (ret)
goto out_fb_dealloc_cmap;
lcd = devm_lcd_device_register(dev, "clps711x-lcd", dev, cfb,
&clps711x_lcd_ops);
if (!IS_ERR(lcd))
return 0;
ret = PTR_ERR(lcd);
unregister_framebuffer(info);
out_fb_dealloc_cmap:
regmap_update_bits(cfb->syscon, SYSCON_OFFSET, SYSCON1_LCDEN, 0);
fb_dealloc_cmap(&info->cmap);
out_fb_release:
framebuffer_release(info);
return ret;
}
static int clps711x_fb_remove(struct platform_device *pdev)
{
struct fb_info *info = platform_get_drvdata(pdev);
struct clps711x_fb_info *cfb = info->par;
regmap_update_bits(cfb->syscon, SYSCON_OFFSET, SYSCON1_LCDEN, 0);
unregister_framebuffer(info);
fb_dealloc_cmap(&info->cmap);
framebuffer_release(info);
return 0;
}
static const struct of_device_id clps711x_fb_dt_ids[] = {
{ .compatible = "cirrus,clps711x-fb", },
{ }
};
MODULE_DEVICE_TABLE(of, clps711x_fb_dt_ids);
static struct platform_driver clps711x_fb_driver = {
.driver = {
.name = CLPS711X_FB_NAME,
.owner = THIS_MODULE,
.of_match_table = clps711x_fb_dt_ids,
},
.probe = clps711x_fb_probe,
.remove = clps711x_fb_remove,
};
module_platform_driver(clps711x_fb_driver);
MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
MODULE_DESCRIPTION("Cirrus Logic CLPS711X FB driver");
MODULE_LICENSE("GPL");
......@@ -1447,10 +1447,8 @@ static int fb_probe(struct platform_device *device)
da8xx_fb_fix.line_length - 1;
/* allocate palette buffer */
par->v_palette_base = dma_alloc_coherent(NULL,
PALETTE_SIZE,
(resource_size_t *)
&par->p_palette_base,
par->v_palette_base = dma_zalloc_coherent(NULL, PALETTE_SIZE,
(resource_size_t *)&par->p_palette_base,
GFP_KERNEL | GFP_DMA);
if (!par->v_palette_base) {
dev_err(&device->dev,
......@@ -1458,7 +1456,6 @@ static int fb_probe(struct platform_device *device)
ret = -EINVAL;
goto err_release_fb_mem;
}
memset(par->v_palette_base, 0, PALETTE_SIZE);
par->irq = platform_get_irq(device, 0);
if (par->irq < 0) {
......
......@@ -224,6 +224,11 @@ struct hvfb_par {
u32 pseudo_palette[16];
u8 init_buf[MAX_VMBUS_PKT_SIZE];
u8 recv_buf[MAX_VMBUS_PKT_SIZE];
/* If true, the VSC notifies the VSP on every framebuffer change */
bool synchronous_fb;
struct notifier_block hvfb_panic_nb;
};
static uint screen_width = HVFB_WIDTH;
......@@ -532,6 +537,19 @@ static void hvfb_update_work(struct work_struct *w)
schedule_delayed_work(&par->dwork, HVFB_UPDATE_DELAY);
}
static int hvfb_on_panic(struct notifier_block *nb,
unsigned long e, void *p)
{
struct hvfb_par *par;
struct fb_info *info;
par = container_of(nb, struct hvfb_par, hvfb_panic_nb);
par->synchronous_fb = true;
info = par->info;
synthvid_update(info);
return NOTIFY_DONE;
}
/* Framebuffer operation handlers */
......@@ -582,14 +600,44 @@ static int hvfb_blank(int blank, struct fb_info *info)
return 1; /* get fb_blank to set the colormap to all black */
}
static void hvfb_cfb_fillrect(struct fb_info *p,
const struct fb_fillrect *rect)
{
struct hvfb_par *par = p->par;
cfb_fillrect(p, rect);
if (par->synchronous_fb)
synthvid_update(p);
}
static void hvfb_cfb_copyarea(struct fb_info *p,
const struct fb_copyarea *area)
{
struct hvfb_par *par = p->par;
cfb_copyarea(p, area);
if (par->synchronous_fb)
synthvid_update(p);
}
static void hvfb_cfb_imageblit(struct fb_info *p,
const struct fb_image *image)
{
struct hvfb_par *par = p->par;
cfb_imageblit(p, image);
if (par->synchronous_fb)
synthvid_update(p);
}
static struct fb_ops hvfb_ops = {
.owner = THIS_MODULE,
.fb_check_var = hvfb_check_var,
.fb_set_par = hvfb_set_par,
.fb_setcolreg = hvfb_setcolreg,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
.fb_fillrect = hvfb_cfb_fillrect,
.fb_copyarea = hvfb_cfb_copyarea,
.fb_imageblit = hvfb_cfb_imageblit,
.fb_blank = hvfb_blank,
};
......@@ -801,6 +849,11 @@ static int hvfb_probe(struct hv_device *hdev,
par->fb_ready = true;
par->synchronous_fb = false;
par->hvfb_panic_nb.notifier_call = hvfb_on_panic;
atomic_notifier_chain_register(&panic_notifier_list,
&par->hvfb_panic_nb);
return 0;
error:
......@@ -820,6 +873,9 @@ static int hvfb_remove(struct hv_device *hdev)
struct fb_info *info = hv_get_drvdata(hdev);
struct hvfb_par *par = info->par;
atomic_notifier_chain_unregister(&panic_notifier_list,
&par->hvfb_panic_nb);
par->update = false;
par->fb_ready = false;
......
......@@ -15,6 +15,7 @@
* GNU General Public License for more details.
*/
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/kernel.h>
......@@ -51,8 +52,7 @@ static int mddi_dummy_probe(struct platform_device *pdev)
{
struct msm_mddi_client_data *client_data = pdev->dev.platform_data;
struct panel_info *panel =
kzalloc(sizeof(struct panel_info), GFP_KERNEL);
int ret;
devm_kzalloc(&pdev->dev, sizeof(struct panel_info), GFP_KERNEL);
if (!panel)
return -ENOMEM;
platform_set_drvdata(pdev, panel);
......@@ -67,24 +67,11 @@ static int mddi_dummy_probe(struct platform_device *pdev)
client_data->fb_resource, 1);
panel->panel_data.fb_data = client_data->private_client_data;
panel->pdev.dev.platform_data = &panel->panel_data;
ret = platform_device_register(&panel->pdev);
if (ret) {
kfree(panel);
return ret;
}
return 0;
}
static int mddi_dummy_remove(struct platform_device *pdev)
{
struct panel_info *panel = platform_get_drvdata(pdev);
kfree(panel);
return 0;
return platform_device_register(&panel->pdev);
}
static struct platform_driver mddi_client_dummy = {
.probe = mddi_dummy_probe,
.remove = mddi_dummy_remove,
.driver = { .name = "mddi_c_dummy" },
};
......
......@@ -262,6 +262,23 @@ static int hdmic_audio_config(struct omap_dss_device *dssdev,
return 0;
}
static int hdmic_set_hdmi_mode(struct omap_dss_device *dssdev, bool hdmi_mode)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
return in->ops.hdmi->set_hdmi_mode(in, hdmi_mode);
}
static int hdmic_set_infoframe(struct omap_dss_device *dssdev,
const struct hdmi_avi_infoframe *avi)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
return in->ops.hdmi->set_infoframe(in, avi);
}
static struct omap_dss_driver hdmic_driver = {
.connect = hdmic_connect,
.disconnect = hdmic_disconnect,
......@@ -277,6 +294,8 @@ static struct omap_dss_driver hdmic_driver = {
.read_edid = hdmic_read_edid,
.detect = hdmic_detect,
.set_hdmi_mode = hdmic_set_hdmi_mode,
.set_hdmi_infoframe = hdmic_set_infoframe,
.audio_enable = hdmic_audio_enable,
.audio_disable = hdmic_audio_disable,
......
......@@ -242,6 +242,24 @@ static int tpd_audio_config(struct omap_dss_device *dssdev,
return in->ops.hdmi->audio_config(in, audio);
}
static int tpd_set_infoframe(struct omap_dss_device *dssdev,
const struct hdmi_avi_infoframe *avi)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
return in->ops.hdmi->set_infoframe(in, avi);
}
static int tpd_set_hdmi_mode(struct omap_dss_device *dssdev,
bool hdmi_mode)
{
struct panel_drv_data *ddata = to_panel_data(dssdev);
struct omap_dss_device *in = ddata->in;
return in->ops.hdmi->set_hdmi_mode(in, hdmi_mode);
}
static const struct omapdss_hdmi_ops tpd_hdmi_ops = {
.connect = tpd_connect,
.disconnect = tpd_disconnect,
......@@ -255,6 +273,8 @@ static const struct omapdss_hdmi_ops tpd_hdmi_ops = {
.read_edid = tpd_read_edid,
.detect = tpd_detect,
.set_infoframe = tpd_set_infoframe,
.set_hdmi_mode = tpd_set_hdmi_mode,
.audio_enable = tpd_audio_enable,
.audio_disable = tpd_audio_disable,
......
......@@ -817,6 +817,10 @@ static int acx565akm_probe(struct spi_device *spi)
bldev = backlight_device_register("acx565akm", &ddata->spi->dev,
ddata, &acx565akm_bl_ops, &props);
if (IS_ERR(bldev)) {
r = PTR_ERR(bldev);
goto err_reg_bl;
}
ddata->bl_dev = bldev;
if (ddata->has_cabc) {
r = sysfs_create_group(&bldev->dev.kobj, &bldev_attr_group);
......@@ -862,6 +866,7 @@ static int acx565akm_probe(struct spi_device *spi)
sysfs_remove_group(&bldev->dev.kobj, &bldev_attr_group);
err_sysfs:
backlight_device_unregister(bldev);
err_reg_bl:
err_detect:
err_gpio:
omap_dss_put_device(ddata->in);
......
......@@ -5,6 +5,7 @@ menuconfig OMAP2_DSS
tristate "OMAP2+ Display Subsystem support"
select VIDEOMODE_HELPERS
select OMAP2_DSS_INIT
select HDMI
help
OMAP2+ Display Subsystem support.
......
......@@ -2879,19 +2879,24 @@ static bool _dispc_mgr_pclk_ok(enum omap_channel channel,
bool dispc_mgr_timings_ok(enum omap_channel channel,
const struct omap_video_timings *timings)
{
bool timings_ok;
timings_ok = _dispc_mgr_size_ok(timings->x_res, timings->y_res);
if (!_dispc_mgr_size_ok(timings->x_res, timings->y_res))
return false;
timings_ok &= _dispc_mgr_pclk_ok(channel, timings->pixelclock);
if (!_dispc_mgr_pclk_ok(channel, timings->pixelclock))
return false;
if (dss_mgr_is_lcd(channel)) {
timings_ok &= _dispc_lcd_timings_ok(timings->hsw, timings->hfp,
/* TODO: OMAP4+ supports interlace for LCD outputs */
if (timings->interlace)
return false;
if (!_dispc_lcd_timings_ok(timings->hsw, timings->hfp,
timings->hbp, timings->vsw, timings->vfp,
timings->vbp);
timings->vbp))
return false;
}
return timings_ok;
return true;
}
static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, int hsw,
......@@ -3257,13 +3262,10 @@ static void dispc_dump_regs(struct seq_file *s)
if (i == OMAP_DSS_CHANNEL_DIGIT)
continue;
DUMPREG(i, DISPC_DEFAULT_COLOR);
DUMPREG(i, DISPC_TRANS_COLOR);
DUMPREG(i, DISPC_TIMING_H);
DUMPREG(i, DISPC_TIMING_V);
DUMPREG(i, DISPC_POL_FREQ);
DUMPREG(i, DISPC_DIVISORo);
DUMPREG(i, DISPC_SIZE_MGR);
DUMPREG(i, DISPC_DATA_CYCLE1);
DUMPREG(i, DISPC_DATA_CYCLE2);
......
......@@ -5658,18 +5658,11 @@ static int omap_dsihw_probe(struct platform_device *dsidev)
return r;
}
static int dsi_unregister_child(struct device *dev, void *data)
{
struct platform_device *pdev = to_platform_device(dev);
platform_device_unregister(pdev);
return 0;
}
static int __exit omap_dsihw_remove(struct platform_device *dsidev)
{
struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
device_for_each_child(&dsidev->dev, NULL, dsi_unregister_child);
of_platform_depopulate(&dsidev->dev);
WARN_ON(dsi->scp_clk_refcount > 0);
......
......@@ -22,6 +22,7 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/hdmi.h>
#include <video/omapdss.h>
#include "dss.h"
......@@ -142,7 +143,7 @@ enum hdmi_audio_samples_perword {
HDMI_AUDIO_ONEWORD_TWOSAMPLES = 1
};
enum hdmi_audio_sample_size {
enum hdmi_audio_sample_size_omap {
HDMI_AUDIO_SAMPLE_16BITS = 0,
HDMI_AUDIO_SAMPLE_24BITS = 1
};
......@@ -178,59 +179,6 @@ enum hdmi_audio_mclk_mode {
HDMI_AUDIO_MCLK_192FS = 7
};
/* INFOFRAME_AVI_ and INFOFRAME_AUDIO_ definitions */
enum hdmi_core_infoframe {
HDMI_INFOFRAME_AVI_DB1Y_RGB = 0,
HDMI_INFOFRAME_AVI_DB1Y_YUV422 = 1,
HDMI_INFOFRAME_AVI_DB1Y_YUV444 = 2,
HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF = 0,
HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_ON = 1,
HDMI_INFOFRAME_AVI_DB1B_NO = 0,
HDMI_INFOFRAME_AVI_DB1B_VERT = 1,
HDMI_INFOFRAME_AVI_DB1B_HORI = 2,
HDMI_INFOFRAME_AVI_DB1B_VERTHORI = 3,
HDMI_INFOFRAME_AVI_DB1S_0 = 0,
HDMI_INFOFRAME_AVI_DB1S_1 = 1,
HDMI_INFOFRAME_AVI_DB1S_2 = 2,
HDMI_INFOFRAME_AVI_DB2C_NO = 0,
HDMI_INFOFRAME_AVI_DB2C_ITU601 = 1,
HDMI_INFOFRAME_AVI_DB2C_ITU709 = 2,
HDMI_INFOFRAME_AVI_DB2C_EC_EXTENDED = 3,
HDMI_INFOFRAME_AVI_DB2M_NO = 0,
HDMI_INFOFRAME_AVI_DB2M_43 = 1,
HDMI_INFOFRAME_AVI_DB2M_169 = 2,
HDMI_INFOFRAME_AVI_DB2R_SAME = 8,
HDMI_INFOFRAME_AVI_DB2R_43 = 9,
HDMI_INFOFRAME_AVI_DB2R_169 = 10,
HDMI_INFOFRAME_AVI_DB2R_149 = 11,
HDMI_INFOFRAME_AVI_DB3ITC_NO = 0,
HDMI_INFOFRAME_AVI_DB3ITC_YES = 1,
HDMI_INFOFRAME_AVI_DB3EC_XVYUV601 = 0,
HDMI_INFOFRAME_AVI_DB3EC_XVYUV709 = 1,
HDMI_INFOFRAME_AVI_DB3Q_DEFAULT = 0,
HDMI_INFOFRAME_AVI_DB3Q_LR = 1,
HDMI_INFOFRAME_AVI_DB3Q_FR = 2,
HDMI_INFOFRAME_AVI_DB3SC_NO = 0,
HDMI_INFOFRAME_AVI_DB3SC_HORI = 1,
HDMI_INFOFRAME_AVI_DB3SC_VERT = 2,
HDMI_INFOFRAME_AVI_DB3SC_HORIVERT = 3,
HDMI_INFOFRAME_AVI_DB5PR_NO = 0,
HDMI_INFOFRAME_AVI_DB5PR_2 = 1,
HDMI_INFOFRAME_AVI_DB5PR_3 = 2,
HDMI_INFOFRAME_AVI_DB5PR_4 = 3,
HDMI_INFOFRAME_AVI_DB5PR_5 = 4,
HDMI_INFOFRAME_AVI_DB5PR_6 = 5,
HDMI_INFOFRAME_AVI_DB5PR_7 = 6,
HDMI_INFOFRAME_AVI_DB5PR_8 = 7,
HDMI_INFOFRAME_AVI_DB5PR_9 = 8,
HDMI_INFOFRAME_AVI_DB5PR_10 = 9,
};
struct hdmi_cm {
int code;
int mode;
};
struct hdmi_video_format {
enum hdmi_packing_mode packing_mode;
u32 y_res; /* Line per panel */
......@@ -239,7 +187,8 @@ struct hdmi_video_format {
struct hdmi_config {
struct omap_video_timings timings;
struct hdmi_cm cm;
struct hdmi_avi_infoframe infoframe;
enum hdmi_core_hdmi_dvi hdmi_dvi_mode;
};
/* HDMI PLL structure */
......@@ -260,7 +209,7 @@ struct hdmi_audio_format {
enum hdmi_audio_justify justification;
enum hdmi_audio_sample_order sample_order;
enum hdmi_audio_samples_perword samples_per_word;
enum hdmi_audio_sample_size sample_size;
enum hdmi_audio_sample_size_omap sample_size;
enum hdmi_audio_blk_strt_end_sig en_sig_blk_strt_end;
};
......@@ -298,47 +247,6 @@ struct hdmi_core_audio_config {
bool en_spdif;
};
/*
* Refer to section 8.2 in HDMI 1.3 specification for
* details about infoframe databytes
*/
struct hdmi_core_infoframe_avi {
/* Y0, Y1 rgb,yCbCr */
u8 db1_format;
/* A0 Active information Present */
u8 db1_active_info;
/* B0, B1 Bar info data valid */
u8 db1_bar_info_dv;
/* S0, S1 scan information */
u8 db1_scan_info;
/* C0, C1 colorimetry */
u8 db2_colorimetry;
/* M0, M1 Aspect ratio (4:3, 16:9) */
u8 db2_aspect_ratio;
/* R0...R3 Active format aspect ratio */
u8 db2_active_fmt_ar;
/* ITC IT content. */
u8 db3_itc;
/* EC0, EC1, EC2 Extended colorimetry */
u8 db3_ec;
/* Q1, Q0 Quantization range */
u8 db3_q_range;
/* SC1, SC0 Non-uniform picture scaling */
u8 db3_nup_scaling;
/* VIC0..6 Video format identification */
u8 db4_videocode;
/* PR0..PR3 Pixel repetition factor */
u8 db5_pixel_repeat;
/* Line number end of top bar */
u16 db6_7_line_eoftop;
/* Line number start of bottom bar */
u16 db8_9_line_sofbottom;
/* Pixel number end of left bar */
u16 db10_11_pixel_eofleft;
/* Pixel number start of right bar */
u16 db12_13_pixel_sofright;
};
struct hdmi_wp_data {
void __iomem *base;
};
......@@ -358,8 +266,6 @@ struct hdmi_phy_data {
struct hdmi_core_data {
void __iomem *base;
struct hdmi_core_infoframe_avi avi_cfg;
};
static inline void hdmi_write_reg(void __iomem *base_addr, const u32 idx,
......@@ -425,9 +331,6 @@ int hdmi_phy_init(struct platform_device *pdev, struct hdmi_phy_data *phy);
int hdmi_phy_parse_lanes(struct hdmi_phy_data *phy, const u32 *lanes);
/* HDMI common funcs */
const struct hdmi_config *hdmi_default_timing(void);
const struct hdmi_config *hdmi_get_timings(int mode, int code);
struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing);
int hdmi_parse_lanes_of(struct platform_device *pdev, struct device_node *ep,
struct hdmi_phy_data *phy);
......
......@@ -281,29 +281,11 @@ static int hdmi_display_check_timing(struct omap_dss_device *dssdev,
static void hdmi_display_set_timing(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
struct hdmi_cm cm;
const struct hdmi_config *t;
mutex_lock(&hdmi.lock);
cm = hdmi_get_code(timings);
hdmi.cfg.cm = cm;
t = hdmi_get_timings(cm.mode, cm.code);
if (t != NULL) {
hdmi.cfg = *t;
dispc_set_tv_pclk(t->timings.pixelclock);
} else {
hdmi.cfg.timings = *timings;
hdmi.cfg.cm.code = 0;
hdmi.cfg.cm.mode = HDMI_DVI;
dispc_set_tv_pclk(timings->pixelclock);
}
DSSDBG("using mode: %s, code %d\n", hdmi.cfg.cm.mode == HDMI_DVI ?
"DVI" : "HDMI", hdmi.cfg.cm.code);
mutex_unlock(&hdmi.lock);
}
......@@ -311,14 +293,7 @@ static void hdmi_display_set_timing(struct omap_dss_device *dssdev,
static void hdmi_display_get_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
const struct hdmi_config *cfg;
struct hdmi_cm cm = hdmi.cfg.cm;
cfg = hdmi_get_timings(cm.mode, cm.code);
if (cfg == NULL)
cfg = hdmi_default_timing();
memcpy(timings, &cfg->timings, sizeof(cfg->timings));
*timings = hdmi.cfg.timings;
}
static void hdmi_dump_regs(struct seq_file *s)
......@@ -516,7 +491,7 @@ static int hdmi_audio_enable(struct omap_dss_device *dssdev)
mutex_lock(&hdmi.lock);
if (!hdmi_mode_has_audio(hdmi.cfg.cm.mode)) {
if (!hdmi_mode_has_audio(hdmi.cfg.hdmi_dvi_mode)) {
r = -EPERM;
goto err;
}
......@@ -554,7 +529,7 @@ static bool hdmi_audio_supported(struct omap_dss_device *dssdev)
mutex_lock(&hdmi.lock);
r = hdmi_mode_has_audio(hdmi.cfg.cm.mode);
r = hdmi_mode_has_audio(hdmi.cfg.hdmi_dvi_mode);
mutex_unlock(&hdmi.lock);
return r;
......@@ -568,7 +543,7 @@ static int hdmi_audio_config(struct omap_dss_device *dssdev,
mutex_lock(&hdmi.lock);
if (!hdmi_mode_has_audio(hdmi.cfg.cm.mode)) {
if (!hdmi_mode_has_audio(hdmi.cfg.hdmi_dvi_mode)) {
r = -EPERM;
goto err;
}
......@@ -615,6 +590,20 @@ static int hdmi_audio_config(struct omap_dss_device *dssdev,
}
#endif
static int hdmi_set_infoframe(struct omap_dss_device *dssdev,
const struct hdmi_avi_infoframe *avi)
{
hdmi.cfg.infoframe = *avi;
return 0;
}
static int hdmi_set_hdmi_mode(struct omap_dss_device *dssdev,
bool hdmi_mode)
{
hdmi.cfg.hdmi_dvi_mode = hdmi_mode ? HDMI_HDMI : HDMI_DVI;
return 0;
}
static const struct omapdss_hdmi_ops hdmi_ops = {
.connect = hdmi_connect,
.disconnect = hdmi_disconnect,
......@@ -627,6 +616,8 @@ static const struct omapdss_hdmi_ops hdmi_ops = {
.get_timings = hdmi_display_get_timings,
.read_edid = hdmi_read_edid,
.set_infoframe = hdmi_set_infoframe,
.set_hdmi_mode = hdmi_set_hdmi_mode,
.audio_enable = hdmi_audio_enable,
.audio_disable = hdmi_audio_disable,
......
......@@ -197,9 +197,7 @@ int hdmi4_read_edid(struct hdmi_core_data *core, u8 *edid, int len)
return l;
}
static void hdmi_core_init(struct hdmi_core_video_config *video_cfg,
struct hdmi_core_infoframe_avi *avi_cfg,
struct hdmi_core_packet_enable_repeat *repeat_cfg)
static void hdmi_core_init(struct hdmi_core_video_config *video_cfg)
{
DSSDBG("Enter hdmi_core_init\n");
......@@ -210,35 +208,6 @@ static void hdmi_core_init(struct hdmi_core_video_config *video_cfg,
video_cfg->pkt_mode = HDMI_PACKETMODERESERVEDVALUE;
video_cfg->hdmi_dvi = HDMI_DVI;
video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK;
/* info frame */
avi_cfg->db1_format = 0;
avi_cfg->db1_active_info = 0;
avi_cfg->db1_bar_info_dv = 0;
avi_cfg->db1_scan_info = 0;
avi_cfg->db2_colorimetry = 0;
avi_cfg->db2_aspect_ratio = 0;
avi_cfg->db2_active_fmt_ar = 0;
avi_cfg->db3_itc = 0;
avi_cfg->db3_ec = 0;
avi_cfg->db3_q_range = 0;
avi_cfg->db3_nup_scaling = 0;
avi_cfg->db4_videocode = 0;
avi_cfg->db5_pixel_repeat = 0;
avi_cfg->db6_7_line_eoftop = 0;
avi_cfg->db8_9_line_sofbottom = 0;
avi_cfg->db10_11_pixel_eofleft = 0;
avi_cfg->db12_13_pixel_sofright = 0;
/* packet enable and repeat */
repeat_cfg->audio_pkt = 0;
repeat_cfg->audio_pkt_repeat = 0;
repeat_cfg->avi_infoframe = 0;
repeat_cfg->avi_infoframe_repeat = 0;
repeat_cfg->gen_cntrl_pkt = 0;
repeat_cfg->gen_cntrl_pkt_repeat = 0;
repeat_cfg->generic_pkt = 0;
repeat_cfg->generic_pkt_repeat = 0;
}
static void hdmi_core_powerdown_disable(struct hdmi_core_data *core)
......@@ -303,80 +272,22 @@ static void hdmi_core_video_config(struct hdmi_core_data *core,
HDMI_CORE_SYS_TMDS_CTRL, cfg->tclk_sel_clkmult, 6, 5);
}
static void hdmi_core_aux_infoframe_avi_config(struct hdmi_core_data *core)
static void hdmi_core_write_avi_infoframe(struct hdmi_core_data *core,
struct hdmi_avi_infoframe *frame)
{
u32 val;
char sum = 0, checksum = 0;
void __iomem *av_base = hdmi_av_base(core);
struct hdmi_core_infoframe_avi info_avi = core->avi_cfg;
sum += 0x82 + 0x002 + 0x00D;
hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_TYPE, 0x082);
hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_VERS, 0x002);
hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_LEN, 0x00D);
val = (info_avi.db1_format << 5) |
(info_avi.db1_active_info << 4) |
(info_avi.db1_bar_info_dv << 2) |
(info_avi.db1_scan_info);
hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(0), val);
sum += val;
val = (info_avi.db2_colorimetry << 6) |
(info_avi.db2_aspect_ratio << 4) |
(info_avi.db2_active_fmt_ar);
hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(1), val);
sum += val;
val = (info_avi.db3_itc << 7) |
(info_avi.db3_ec << 4) |
(info_avi.db3_q_range << 2) |
(info_avi.db3_nup_scaling);
hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(2), val);
sum += val;
hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(3),
info_avi.db4_videocode);
sum += info_avi.db4_videocode;
val = info_avi.db5_pixel_repeat;
hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(4), val);
sum += val;
val = info_avi.db6_7_line_eoftop & 0x00FF;
hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(5), val);
sum += val;
val = ((info_avi.db6_7_line_eoftop >> 8) & 0x00FF);
hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(6), val);
sum += val;
val = info_avi.db8_9_line_sofbottom & 0x00FF;
hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(7), val);
sum += val;
val = ((info_avi.db8_9_line_sofbottom >> 8) & 0x00FF);
hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(8), val);
sum += val;
val = info_avi.db10_11_pixel_eofleft & 0x00FF;
hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(9), val);
sum += val;
val = ((info_avi.db10_11_pixel_eofleft >> 8) & 0x00FF);
hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(10), val);
sum += val;
val = info_avi.db12_13_pixel_sofright & 0x00FF;
hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(11), val);
sum += val;
val = ((info_avi.db12_13_pixel_sofright >> 8) & 0x00FF);
hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_DBYTE(12), val);
sum += val;
u8 data[HDMI_INFOFRAME_SIZE(AVI)];
int i;
checksum = 0x100 - sum;
hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_CHSUM, checksum);
hdmi_avi_infoframe_pack(frame, data, sizeof(data));
print_hex_dump_debug("AVI: ", DUMP_PREFIX_NONE, 16, 1, data,
HDMI_INFOFRAME_SIZE(AVI), false);
for (i = 0; i < sizeof(data); ++i) {
hdmi_write_reg(av_base, HDMI_CORE_AV_AVI_BASE + i * 4,
data[i]);
}
}
static void hdmi_core_av_packet_config(struct hdmi_core_data *core,
......@@ -404,11 +315,10 @@ void hdmi4_configure(struct hdmi_core_data *core,
struct omap_video_timings video_timing;
struct hdmi_video_format video_format;
/* HDMI core */
struct hdmi_core_infoframe_avi *avi_cfg = &core->avi_cfg;
struct hdmi_core_video_config v_core_cfg;
struct hdmi_core_packet_enable_repeat repeat_cfg;
struct hdmi_core_packet_enable_repeat repeat_cfg = { 0 };
hdmi_core_init(&v_core_cfg, avi_cfg, &repeat_cfg);
hdmi_core_init(&v_core_cfg);
hdmi_wp_init_vid_fmt_timings(&video_format, &video_timing, cfg);
......@@ -431,37 +341,15 @@ void hdmi4_configure(struct hdmi_core_data *core,
hdmi_core_powerdown_disable(core);
v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL;
v_core_cfg.hdmi_dvi = cfg->cm.mode;
v_core_cfg.hdmi_dvi = cfg->hdmi_dvi_mode;
hdmi_core_video_config(core, &v_core_cfg);
/* release software reset in the core */
hdmi_core_swreset_release(core);
/*
* configure packet
* info frame video see doc CEA861-D page 65
*/
avi_cfg->db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB;
avi_cfg->db1_active_info =
HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF;
avi_cfg->db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO;
avi_cfg->db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0;
avi_cfg->db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO;
avi_cfg->db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO;
avi_cfg->db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME;
avi_cfg->db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO;
avi_cfg->db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601;
avi_cfg->db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT;
avi_cfg->db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO;
avi_cfg->db4_videocode = cfg->cm.code;
avi_cfg->db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO;
avi_cfg->db6_7_line_eoftop = 0;
avi_cfg->db8_9_line_sofbottom = 0;
avi_cfg->db10_11_pixel_eofleft = 0;
avi_cfg->db12_13_pixel_sofright = 0;
hdmi_core_aux_infoframe_avi_config(core);
if (cfg->hdmi_dvi_mode == HDMI_HDMI) {
hdmi_core_write_avi_infoframe(core, &cfg->infoframe);
/* enable/repeat the infoframe */
repeat_cfg.avi_infoframe = HDMI_PACKETENABLE;
......@@ -469,6 +357,8 @@ void hdmi4_configure(struct hdmi_core_data *core,
/* wakeup */
repeat_cfg.audio_pkt = HDMI_PACKETENABLE;
repeat_cfg.audio_pkt_repeat = HDMI_PACKETREPEATON;
}
hdmi_core_av_packet_config(core, repeat_cfg);
}
......
......@@ -145,6 +145,7 @@
#define HDMI_CORE_AV_DPD 0xF4
#define HDMI_CORE_AV_PB_CTRL1 0xF8
#define HDMI_CORE_AV_PB_CTRL2 0xFC
#define HDMI_CORE_AV_AVI_BASE 0x100
#define HDMI_CORE_AV_AVI_TYPE 0x100
#define HDMI_CORE_AV_AVI_VERS 0x104
#define HDMI_CORE_AV_AVI_LEN 0x108
......
......@@ -299,29 +299,11 @@ static int hdmi_display_check_timing(struct omap_dss_device *dssdev,
static void hdmi_display_set_timing(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
struct hdmi_cm cm;
const struct hdmi_config *t;
mutex_lock(&hdmi.lock);
cm = hdmi_get_code(timings);
hdmi.cfg.cm = cm;
t = hdmi_get_timings(cm.mode, cm.code);
if (t != NULL) {
hdmi.cfg = *t;
dispc_set_tv_pclk(t->timings.pixelclock);
} else {
hdmi.cfg.timings = *timings;
hdmi.cfg.cm.code = 0;
hdmi.cfg.cm.mode = HDMI_DVI;
dispc_set_tv_pclk(timings->pixelclock);
}
DSSDBG("using mode: %s, code %d\n", hdmi.cfg.cm.mode == HDMI_DVI ?
"DVI" : "HDMI", hdmi.cfg.cm.code);
mutex_unlock(&hdmi.lock);
}
......@@ -329,14 +311,7 @@ static void hdmi_display_set_timing(struct omap_dss_device *dssdev,
static void hdmi_display_get_timings(struct omap_dss_device *dssdev,
struct omap_video_timings *timings)
{
const struct hdmi_config *cfg;
struct hdmi_cm cm = hdmi.cfg.cm;
cfg = hdmi_get_timings(cm.mode, cm.code);
if (cfg == NULL)
cfg = hdmi_default_timing();
memcpy(timings, &cfg->timings, sizeof(cfg->timings));
*timings = hdmi.cfg.timings;
}
static void hdmi_dump_regs(struct seq_file *s)
......@@ -541,7 +516,7 @@ static int hdmi_audio_enable(struct omap_dss_device *dssdev)
mutex_lock(&hdmi.lock);
if (!hdmi_mode_has_audio(hdmi.cfg.cm.mode)) {
if (!hdmi_mode_has_audio(hdmi.cfg.hdmi_dvi_mode)) {
r = -EPERM;
goto err;
}
......@@ -579,7 +554,7 @@ static bool hdmi_audio_supported(struct omap_dss_device *dssdev)
mutex_lock(&hdmi.lock);
r = hdmi_mode_has_audio(hdmi.cfg.cm.mode);
r = hdmi_mode_has_audio(hdmi.cfg.hdmi_dvi_mode);
mutex_unlock(&hdmi.lock);
return r;
......@@ -593,7 +568,7 @@ static int hdmi_audio_config(struct omap_dss_device *dssdev,
mutex_lock(&hdmi.lock);
if (!hdmi_mode_has_audio(hdmi.cfg.cm.mode)) {
if (!hdmi_mode_has_audio(hdmi.cfg.hdmi_dvi_mode)) {
r = -EPERM;
goto err;
}
......@@ -640,6 +615,20 @@ static int hdmi_audio_config(struct omap_dss_device *dssdev,
}
#endif
static int hdmi_set_infoframe(struct omap_dss_device *dssdev,
const struct hdmi_avi_infoframe *avi)
{
hdmi.cfg.infoframe = *avi;
return 0;
}
static int hdmi_set_hdmi_mode(struct omap_dss_device *dssdev,
bool hdmi_mode)
{
hdmi.cfg.hdmi_dvi_mode = hdmi_mode ? HDMI_HDMI : HDMI_DVI;
return 0;
}
static const struct omapdss_hdmi_ops hdmi_ops = {
.connect = hdmi_connect,
.disconnect = hdmi_disconnect,
......@@ -652,6 +641,8 @@ static const struct omapdss_hdmi_ops hdmi_ops = {
.get_timings = hdmi_display_get_timings,
.read_edid = hdmi_read_edid,
.set_infoframe = hdmi_set_infoframe,
.set_hdmi_mode = hdmi_set_hdmi_mode,
.audio_enable = hdmi_audio_enable,
.audio_disable = hdmi_audio_disable,
......
......@@ -290,7 +290,6 @@ void hdmi5_core_dump(struct hdmi_core_data *core, struct seq_file *s)
}
static void hdmi_core_init(struct hdmi_core_vid_config *video_cfg,
struct hdmi_core_infoframe_avi *avi_cfg,
struct hdmi_config *cfg)
{
DSSDBG("hdmi_core_init\n");
......@@ -312,27 +311,8 @@ static void hdmi_core_init(struct hdmi_core_vid_config *video_cfg,
video_cfg->vblank_osc = 0; /* Always 0 - need to confirm */
video_cfg->vblank = cfg->timings.vsw +
cfg->timings.vfp + cfg->timings.vbp;
video_cfg->v_fc_config.cm.mode = cfg->cm.mode;
video_cfg->v_fc_config.hdmi_dvi_mode = cfg->hdmi_dvi_mode;
video_cfg->v_fc_config.timings.interlace = cfg->timings.interlace;
/* info frame */
avi_cfg->db1_format = 0;
avi_cfg->db1_active_info = 0;
avi_cfg->db1_bar_info_dv = 0;
avi_cfg->db1_scan_info = 0;
avi_cfg->db2_colorimetry = 0;
avi_cfg->db2_aspect_ratio = 0;
avi_cfg->db2_active_fmt_ar = 0;
avi_cfg->db3_itc = 0;
avi_cfg->db3_ec = 0;
avi_cfg->db3_q_range = 0;
avi_cfg->db3_nup_scaling = 0;
avi_cfg->db4_videocode = 0;
avi_cfg->db5_pixel_repeat = 0;
avi_cfg->db6_7_line_eoftop = 0;
avi_cfg->db8_9_line_sofbottom = 0;
avi_cfg->db10_11_pixel_eofleft = 0;
avi_cfg->db12_13_pixel_sofright = 0;
}
/* DSS_HDMI_CORE_VIDEO_CONFIG */
......@@ -398,7 +378,7 @@ static void hdmi_core_video_config(struct hdmi_core_data *core,
/* select DVI mode */
REG_FLD_MOD(base, HDMI_CORE_FC_INVIDCONF,
cfg->v_fc_config.cm.mode, 3, 3);
cfg->v_fc_config.hdmi_dvi_mode, 3, 3);
}
static void hdmi_core_config_video_packetizer(struct hdmi_core_data *core)
......@@ -438,24 +418,60 @@ static void hdmi_core_config_video_sampler(struct hdmi_core_data *core)
REG_FLD_MOD(core->base, HDMI_CORE_TX_INVID0, video_mapping, 4, 0);
}
static void hdmi_core_aux_infoframe_avi_config(struct hdmi_core_data *core)
static void hdmi_core_write_avi_infoframe(struct hdmi_core_data *core,
struct hdmi_avi_infoframe *frame)
{
void __iomem *base = core->base;
struct hdmi_core_infoframe_avi avi = core->avi_cfg;
REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF0, avi.db1_format, 1, 0);
REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF0, avi.db1_active_info, 6, 6);
REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF0, avi.db1_bar_info_dv, 3, 2);
REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF0, avi.db1_scan_info, 5, 4);
REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF1, avi.db2_colorimetry, 7, 6);
REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF1, avi.db2_aspect_ratio, 5, 4);
REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF1, avi.db2_active_fmt_ar, 3, 0);
REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF2, avi.db3_itc, 7, 7);
REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF2, avi.db3_ec, 6, 4);
REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF2, avi.db3_q_range, 3, 2);
REG_FLD_MOD(base, HDMI_CORE_FC_AVICONF2, avi.db3_nup_scaling, 1, 0);
REG_FLD_MOD(base, HDMI_CORE_FC_AVIVID, avi.db4_videocode, 6, 0);
REG_FLD_MOD(base, HDMI_CORE_FC_PRCONF, avi.db5_pixel_repeat, 3, 0);
u8 data[HDMI_INFOFRAME_SIZE(AVI)];
u8 *ptr;
unsigned y, a, b, s;
unsigned c, m, r;
unsigned itc, ec, q, sc;
unsigned vic;
unsigned yq, cn, pr;
hdmi_avi_infoframe_pack(frame, data, sizeof(data));
print_hex_dump_debug("AVI: ", DUMP_PREFIX_NONE, 16, 1, data,
HDMI_INFOFRAME_SIZE(AVI), false);
ptr = data + HDMI_INFOFRAME_HEADER_SIZE;
y = (ptr[0] >> 5) & 0x3;
a = (ptr[0] >> 4) & 0x1;
b = (ptr[0] >> 2) & 0x3;
s = (ptr[0] >> 0) & 0x3;
c = (ptr[1] >> 6) & 0x3;
m = (ptr[1] >> 4) & 0x3;
r = (ptr[1] >> 0) & 0x3;
itc = (ptr[2] >> 7) & 0x1;
ec = (ptr[2] >> 4) & 0x7;
q = (ptr[2] >> 2) & 0x3;
sc = (ptr[2] >> 0) & 0x3;
vic = ptr[3];
yq = (ptr[4] >> 6) & 0x3;
cn = (ptr[4] >> 4) & 0x3;
pr = (ptr[4] >> 0) & 0xf;
hdmi_write_reg(base, HDMI_CORE_FC_AVICONF0,
(a << 6) | (s << 4) | (b << 2) | (y << 0));
hdmi_write_reg(base, HDMI_CORE_FC_AVICONF1,
(c << 6) | (m << 4) | (r << 0));
hdmi_write_reg(base, HDMI_CORE_FC_AVICONF2,
(itc << 7) | (ec << 4) | (q << 2) | (sc << 0));
hdmi_write_reg(base, HDMI_CORE_FC_AVIVID, vic);
hdmi_write_reg(base, HDMI_CORE_FC_AVICONF3,
(yq << 2) | (cn << 0));
REG_FLD_MOD(base, HDMI_CORE_FC_PRCONF, pr, 3, 0);
}
static void hdmi_core_csc_config(struct hdmi_core_data *core,
......@@ -497,10 +513,8 @@ static void hdmi_core_configure_range(struct hdmi_core_data *core)
/* support limited range with 24 bit color depth for now */
csc_coeff = csc_table_deepcolor[0];
core->avi_cfg.db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_LR;
hdmi_core_csc_config(core, csc_coeff);
hdmi_core_aux_infoframe_avi_config(core);
}
static void hdmi_core_enable_video_path(struct hdmi_core_data *core)
......@@ -591,11 +605,10 @@ void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
struct omap_video_timings video_timing;
struct hdmi_video_format video_format;
struct hdmi_core_vid_config v_core_cfg;
struct hdmi_core_infoframe_avi *avi_cfg = &core->avi_cfg;
hdmi_core_mask_interrupts(core);
hdmi_core_init(&v_core_cfg, avi_cfg, cfg);
hdmi_core_init(&v_core_cfg, cfg);
hdmi_wp_init_vid_fmt_timings(&video_format, &video_timing, cfg);
......@@ -608,7 +621,9 @@ void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
hdmi_wp_video_config_interface(wp, &video_timing);
/* support limited range with 24 bit color depth for now */
hdmi_core_configure_range(core);
cfg->infoframe.quantization_range = HDMI_QUANTIZATION_RANGE_LIMITED;
/*
* configure core video part, set software reset in the core
......@@ -621,29 +636,8 @@ void hdmi5_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp,
hdmi_core_config_csc(core);
hdmi_core_config_video_sampler(core);
/*
* configure packet info frame video see doc CEA861-D page 65
*/
avi_cfg->db1_format = HDMI_INFOFRAME_AVI_DB1Y_RGB;
avi_cfg->db1_active_info =
HDMI_INFOFRAME_AVI_DB1A_ACTIVE_FORMAT_OFF;
avi_cfg->db1_bar_info_dv = HDMI_INFOFRAME_AVI_DB1B_NO;
avi_cfg->db1_scan_info = HDMI_INFOFRAME_AVI_DB1S_0;
avi_cfg->db2_colorimetry = HDMI_INFOFRAME_AVI_DB2C_NO;
avi_cfg->db2_aspect_ratio = HDMI_INFOFRAME_AVI_DB2M_NO;
avi_cfg->db2_active_fmt_ar = HDMI_INFOFRAME_AVI_DB2R_SAME;
avi_cfg->db3_itc = HDMI_INFOFRAME_AVI_DB3ITC_NO;
avi_cfg->db3_ec = HDMI_INFOFRAME_AVI_DB3EC_XVYUV601;
avi_cfg->db3_q_range = HDMI_INFOFRAME_AVI_DB3Q_DEFAULT;
avi_cfg->db3_nup_scaling = HDMI_INFOFRAME_AVI_DB3SC_NO;
avi_cfg->db4_videocode = cfg->cm.code;
avi_cfg->db5_pixel_repeat = HDMI_INFOFRAME_AVI_DB5PR_NO;
avi_cfg->db6_7_line_eoftop = 0;
avi_cfg->db8_9_line_sofbottom = 0;
avi_cfg->db10_11_pixel_eofleft = 0;
avi_cfg->db12_13_pixel_sofright = 0;
hdmi_core_aux_infoframe_avi_config(core);
if (cfg->hdmi_dvi_mode == HDMI_HDMI)
hdmi_core_write_avi_infoframe(core, &cfg->infoframe);
hdmi_core_enable_video_path(core);
......
/*
* Logic for the below structure :
* user enters the CEA or VESA timings by specifying the HDMI/DVI code.
* There is a correspondence between CEA/VESA timing and code, please
* refer to section 6.3 in HDMI 1.3 specification for timing code.
*
* In the below structure, cea_vesa_timings corresponds to all OMAP4
* supported CEA and VESA timing values.code_cea corresponds to the CEA
* code, It is used to get the timing from cea_vesa_timing array.Similarly
* with code_vesa. Code_index is used for back mapping, that is once EDID
* is read from the TV, EDID is parsed to find the timing values and then
* map it to corresponding CEA or VESA index.
*/
#define DSS_SUBSYS_NAME "HDMI"
#include <linux/kernel.h>
......@@ -22,308 +8,6 @@
#include "hdmi.h"
static const struct hdmi_config cea_timings[] = {
{
{ 640, 480, 25200000, 96, 16, 48, 2, 10, 33,
OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
false, },
{ 1, HDMI_HDMI },
},
{
{ 720, 480, 27027000, 62, 16, 60, 6, 9, 30,
OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
false, },
{ 2, HDMI_HDMI },
},
{
{ 1280, 720, 74250000, 40, 110, 220, 5, 5, 20,
OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
false, },
{ 4, HDMI_HDMI },
},
{
{ 1920, 540, 74250000, 44, 88, 148, 5, 2, 15,
OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
true, },
{ 5, HDMI_HDMI },
},
{
{ 1440, 240, 27027000, 124, 38, 114, 3, 4, 15,
OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
true, },
{ 6, HDMI_HDMI },
},
{
{ 1920, 1080, 148500000, 44, 88, 148, 5, 4, 36,
OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
false, },
{ 16, HDMI_HDMI },
},
{
{ 720, 576, 27000000, 64, 12, 68, 5, 5, 39,
OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
false, },
{ 17, HDMI_HDMI },
},
{
{ 1280, 720, 74250000, 40, 440, 220, 5, 5, 20,
OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
false, },
{ 19, HDMI_HDMI },
},
{
{ 1920, 540, 74250000, 44, 528, 148, 5, 2, 15,
OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
true, },
{ 20, HDMI_HDMI },
},
{
{ 1440, 288, 27000000, 126, 24, 138, 3, 2, 19,
OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
true, },
{ 21, HDMI_HDMI },
},
{
{ 1440, 576, 54000000, 128, 24, 136, 5, 5, 39,
OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
false, },
{ 29, HDMI_HDMI },
},
{
{ 1920, 1080, 148500000, 44, 528, 148, 5, 4, 36,
OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
false, },
{ 31, HDMI_HDMI },
},
{
{ 1920, 1080, 74250000, 44, 638, 148, 5, 4, 36,
OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
false, },
{ 32, HDMI_HDMI },
},
{
{ 2880, 480, 108108000, 248, 64, 240, 6, 9, 30,
OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
false, },
{ 35, HDMI_HDMI },
},
{
{ 2880, 576, 108000000, 256, 48, 272, 5, 5, 39,
OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
false, },
{ 37, HDMI_HDMI },
},
};
static const struct hdmi_config vesa_timings[] = {
/* VESA From Here */
{
{ 640, 480, 25175000, 96, 16, 48, 2, 11, 31,
OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
false, },
{ 4, HDMI_DVI },
},
{
{ 800, 600, 40000000, 128, 40, 88, 4, 1, 23,
OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
false, },
{ 9, HDMI_DVI },
},
{
{ 848, 480, 33750000, 112, 16, 112, 8, 6, 23,
OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
false, },
{ 0xE, HDMI_DVI },
},
{
{ 1280, 768, 79500000, 128, 64, 192, 7, 3, 20,
OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
false, },
{ 0x17, HDMI_DVI },
},
{
{ 1280, 800, 83500000, 128, 72, 200, 6, 3, 22,
OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
false, },
{ 0x1C, HDMI_DVI },
},
{
{ 1360, 768, 85500000, 112, 64, 256, 6, 3, 18,
OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
false, },
{ 0x27, HDMI_DVI },
},
{
{ 1280, 960, 108000000, 112, 96, 312, 3, 1, 36,
OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
false, },
{ 0x20, HDMI_DVI },
},
{
{ 1280, 1024, 108000000, 112, 48, 248, 3, 1, 38,
OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
false, },
{ 0x23, HDMI_DVI },
},
{
{ 1024, 768, 65000000, 136, 24, 160, 6, 3, 29,
OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_LOW,
false, },
{ 0x10, HDMI_DVI },
},
{
{ 1400, 1050, 121750000, 144, 88, 232, 4, 3, 32,
OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
false, },
{ 0x2A, HDMI_DVI },
},
{
{ 1440, 900, 106500000, 152, 80, 232, 6, 3, 25,
OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
false, },
{ 0x2F, HDMI_DVI },
},
{
{ 1680, 1050, 146250000, 176 , 104, 280, 6, 3, 30,
OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_LOW,
false, },
{ 0x3A, HDMI_DVI },
},
{
{ 1366, 768, 85500000, 143, 70, 213, 3, 3, 24,
OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
false, },
{ 0x51, HDMI_DVI },
},
{
{ 1920, 1080, 148500000, 44, 148, 80, 5, 4, 36,
OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
false, },
{ 0x52, HDMI_DVI },
},
{
{ 1280, 768, 68250000, 32, 48, 80, 7, 3, 12,
OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
false, },
{ 0x16, HDMI_DVI },
},
{
{ 1400, 1050, 101000000, 32, 48, 80, 4, 3, 23,
OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
false, },
{ 0x29, HDMI_DVI },
},
{
{ 1680, 1050, 119000000, 32, 48, 80, 6, 3, 21,
OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
false, },
{ 0x39, HDMI_DVI },
},
{
{ 1280, 800, 79500000, 32, 48, 80, 6, 3, 14,
OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
false, },
{ 0x1B, HDMI_DVI },
},
{
{ 1280, 720, 74250000, 40, 110, 220, 5, 5, 20,
OMAPDSS_SIG_ACTIVE_HIGH, OMAPDSS_SIG_ACTIVE_HIGH,
false, },
{ 0x55, HDMI_DVI },
},
{
{ 1920, 1200, 154000000, 32, 48, 80, 6, 3, 26,
OMAPDSS_SIG_ACTIVE_LOW, OMAPDSS_SIG_ACTIVE_HIGH,
false, },
{ 0x44, HDMI_DVI },
},
};
const struct hdmi_config *hdmi_default_timing(void)
{
return &vesa_timings[0];
}
static const struct hdmi_config *hdmi_find_timing(int code,
const struct hdmi_config *timings_arr, int len)
{
int i;
for (i = 0; i < len; i++) {
if (timings_arr[i].cm.code == code)
return &timings_arr[i];
}
return NULL;
}
const struct hdmi_config *hdmi_get_timings(int mode, int code)
{
const struct hdmi_config *arr;
int len;
if (mode == HDMI_DVI) {
arr = vesa_timings;
len = ARRAY_SIZE(vesa_timings);
} else {
arr = cea_timings;
len = ARRAY_SIZE(cea_timings);
}
return hdmi_find_timing(code, arr, len);
}
static bool hdmi_timings_compare(struct omap_video_timings *timing1,
const struct omap_video_timings *timing2)
{
int timing1_vsync, timing1_hsync, timing2_vsync, timing2_hsync;
if ((DIV_ROUND_CLOSEST(timing2->pixelclock, 1000000) ==
DIV_ROUND_CLOSEST(timing1->pixelclock, 1000000)) &&
(timing2->x_res == timing1->x_res) &&
(timing2->y_res == timing1->y_res)) {
timing2_hsync = timing2->hfp + timing2->hsw + timing2->hbp;
timing1_hsync = timing1->hfp + timing1->hsw + timing1->hbp;
timing2_vsync = timing2->vfp + timing2->vsw + timing2->vbp;
timing1_vsync = timing1->vfp + timing1->vsw + timing1->vbp;
DSSDBG("timing1_hsync = %d timing1_vsync = %d"\
"timing2_hsync = %d timing2_vsync = %d\n",
timing1_hsync, timing1_vsync,
timing2_hsync, timing2_vsync);
if ((timing1_hsync == timing2_hsync) &&
(timing1_vsync == timing2_vsync)) {
return true;
}
}
return false;
}
struct hdmi_cm hdmi_get_code(struct omap_video_timings *timing)
{
int i;
struct hdmi_cm cm = {-1};
DSSDBG("hdmi_get_code\n");
for (i = 0; i < ARRAY_SIZE(cea_timings); i++) {
if (hdmi_timings_compare(timing, &cea_timings[i].timings)) {
cm = cea_timings[i].cm;
goto end;
}
}
for (i = 0; i < ARRAY_SIZE(vesa_timings); i++) {
if (hdmi_timings_compare(timing, &vesa_timings[i].timings)) {
cm = vesa_timings[i].cm;
goto end;
}
}
end:
return cm;
}
int hdmi_parse_lanes_of(struct platform_device *pdev, struct device_node *ep,
struct hdmi_phy_data *phy)
{
......
......@@ -932,7 +932,7 @@ static int s3c24xxfb_probe(struct platform_device *pdev,
goto release_irq;
}
clk_enable(info->clk);
clk_prepare_enable(info->clk);
dprintk("got and enabled clock\n");
usleep_range(1000, 1100);
......@@ -996,7 +996,7 @@ static int s3c24xxfb_probe(struct platform_device *pdev,
free_video_memory:
s3c2410fb_unmap_video_memory(fbinfo);
release_clock:
clk_disable(info->clk);
clk_disable_unprepare(info->clk);
clk_put(info->clk);
release_irq:
free_irq(irq, info);
......@@ -1038,7 +1038,7 @@ static int s3c2410fb_remove(struct platform_device *pdev)
s3c2410fb_unmap_video_memory(fbinfo);
if (info->clk) {
clk_disable(info->clk);
clk_disable_unprepare(info->clk);
clk_put(info->clk);
info->clk = NULL;
}
......@@ -1070,7 +1070,7 @@ static int s3c2410fb_suspend(struct platform_device *dev, pm_message_t state)
* before the clock goes off again (bjd) */
usleep_range(1000, 1100);
clk_disable(info->clk);
clk_disable_unprepare(info->clk);
return 0;
}
......@@ -1080,7 +1080,7 @@ static int s3c2410fb_resume(struct platform_device *dev)
struct fb_info *fbinfo = platform_get_drvdata(dev);
struct s3c2410fb_info *info = fbinfo->par;
clk_enable(info->clk);
clk_prepare_enable(info->clk);
usleep_range(1000, 1100);
s3c2410fb_init_registers(fbinfo);
......
......@@ -1511,7 +1511,7 @@ SiS_Get310DRAMType(struct SiS_Private *SiS_Pr)
} else if(SiS_Pr->ChipType >= SIS_340) {
/* TODO */
data = 0;
} if(SiS_Pr->ChipType >= SIS_661) {
} else if(SiS_Pr->ChipType >= SIS_661) {
if(SiS_Pr->SiS_ROMNew) {
data = ((SiS_GetReg(SiS_Pr->SiS_P3d4,0x78) & 0xc0) >> 6);
} else {
......
......@@ -1572,10 +1572,6 @@ sisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
/* Adapt RGB settings */
sisfb_bpp_to_var(ivideo, var);
/* Sanity check for offsets */
if(var->xoffset < 0) var->xoffset = 0;
if(var->yoffset < 0) var->yoffset = 0;
if(var->xres > var->xres_virtual)
var->xres_virtual = var->xres;
......
......@@ -553,7 +553,7 @@ static inline struct apertures_struct *alloc_apertures(unsigned int max_num) {
#define fb_memcpy_fromfb sbus_memcpy_fromio
#define fb_memcpy_tofb sbus_memcpy_toio
#elif defined(__i386__) || defined(__alpha__) || defined(__x86_64__) || defined(__hppa__) || defined(__sh__) || defined(__powerpc__) || defined(__avr32__) || defined(__bfin__)
#elif defined(__i386__) || defined(__alpha__) || defined(__x86_64__) || defined(__hppa__) || defined(__sh__) || defined(__powerpc__) || defined(__avr32__) || defined(__bfin__) || defined(__arm__)
#define fb_readb __raw_readb
#define fb_readw __raw_readw
......
......@@ -61,6 +61,7 @@ struct omap_overlay_manager;
struct dss_lcd_mgr_config;
struct snd_aes_iec958;
struct snd_cea_861_aud_if;
struct hdmi_avi_infoframe;
enum omap_display_type {
OMAP_DISPLAY_TYPE_NONE = 0,
......@@ -631,6 +632,10 @@ struct omapdss_hdmi_ops {
int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
bool (*detect)(struct omap_dss_device *dssdev);
int (*set_hdmi_mode)(struct omap_dss_device *dssdev, bool hdmi_mode);
int (*set_infoframe)(struct omap_dss_device *dssdev,
const struct hdmi_avi_infoframe *avi);
/*
* Note: These functions might sleep. Do not call while
* holding a spinlock/readlock.
......@@ -850,6 +855,10 @@ struct omap_dss_driver {
int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len);
bool (*detect)(struct omap_dss_device *dssdev);
int (*set_hdmi_mode)(struct omap_dss_device *dssdev, bool hdmi_mode);
int (*set_hdmi_infoframe)(struct omap_dss_device *dssdev,
const struct hdmi_avi_infoframe *avi);
/*
* For display drivers that support audio. This encompasses
* HDMI and DisplayPort at the moment.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment