* Re: [GIT PULL] viafb fixes for 2.6.39
From: Paul Mundt @ 2011-03-23 12:31 UTC (permalink / raw)
To: linux-fbdev
In-Reply-To: <4D89E6B5.8080005@gmx.de>
On Wed, Mar 23, 2011 at 01:25:25PM +0100, Florian Tobias Schandinat wrote:
> please pull the viafb fixes below.
> They fix the handling of refresh rates which should now work (or at least
> work much better than it did before). Especially the initial refresh rate
> as passed in via module parameter is now handled correct. Before these
> patches this didn't work for higher refresh rates.
>
I half expected there to be another pull request while I was writing mine
up.. :-)
I'll pull them once Linus pulls and make sure they're lumped in for -rc2.
^ permalink raw reply
* [GIT PULL] fbdev updates for 2.6.39-rc1, part 2.
From: Paul Mundt @ 2011-03-23 12:28 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-fbdev, linux-kernel
Here's the second batch of fbdev updates. The bulk of this is OMAP DSS
churn that had some dependencies on both the ARM and OMAP merges that
have since settled. The rest is basically random fixes, svgalib
modernization, and the usual smattering of driver updates.
This does not yet include Andy Whitcroft's registration locking or the
suspend/resume console locking fixes as we still need to make a few
changes and do some more testing (as well as getting confirmation that
things still work in both cases). My intention is to have that sorted out
for -rc2.
I noticed a few other fb drivers and churn popped up from various other
trees, but that should hopefully begin to slow down now that things are
for the most part being centrally maintained (the bulk of the ARM SoC trees
for example seem to prefer to lump all of their driver changes together
rather than going through subsystem trees -- basically all of them but
OMAP and SH/R-Mobile, but in general folks have been pretty good with
making sure patches still hit the lists and at least have some tentative
review, as with the unicore32 merge).
Please pull from:
master.kernel.org:/pub/scm/linux/kernel/git/lethal/fbdev-2.6.git
Which contains:
Aaro Koskinen (6):
sisfb: POST should fail if R/W test fails
sisfb: move XGI POST RAM type detection into a subroutine
sisfb: add subroutine for detecting XGI Z9
sisfb: add RAM type detection for XGI Z9
sisfb: move XGI POST DDR2 bootup code into subroutines
sisfb: add support for XGI Z9 DDR2 POST
Andreas Bießmann (2):
atmel_lcdfb: implement inverted contrast pwm
atmel_lcdfb: add fb_blank function
Archit Taneja (15):
OMAP2PLUS: DSS2: Generalize naming of PRCM related clock enums in DSS driver
OMAP2PLUS: DSS2: Generalize external clock names in struct dss of dss.c
OMAP: DSS2: Have separate irq handlers for DISPC and DSI
OMAP2PLUS: DSS2: FEATURES: DISPC overlay code cleanup
OMAP2PLUS: DSS2: FEATURES: Function to Provide the max fck supported
OMAP2PLUS: DSS2: Make members of dss_clk_source generic
OMAP2PLUS: DSS2: Use dss features to get clock source names of current OMAP
OMAP2PLUS: DSS2: DSI: Generalize DSI PLL Clock Naming
OMAP: DSS2: Functions to request/release DSI VCs
OMAP: DSS2: Use request / release calls in Taal for DSI Virtual Channels.
OMAP2PLUS: DSS2: Cleanup clock source related code
OMAP4: DSS2: Clock source changes for OMAP4
OMAP2PLUS: DSS2: FEATURES: Fix usage of dss_reg_field and dss_clk_source_name
OMAP: DSS2: FEATURES: Functions to return min and max values of parameters
OMAP: DSS2: FEATURES: DSI PLL parameter cleanup
Axel Lin (7):
video: hpfb: use resource_size()
video: sh7760fb: use resource_size()
video: ffb: fix ffb_probe error path
video: s3c-fb: return proper error if clk_get fails
video: hecubafb: add __devexit_p around reference to hecubafb_remove
video: metronomefb: add __devexit_p around reference to metronomefb_remove
video: add missing framebuffer_release in error path
Dan Carpenter (1):
fbdev: sh_mobile_lcdc: checking NULL instead of IS_ERR()
Dave Airlie (1):
fbcon: fix situation where fbcon gets deinitialised and can't reinit.
David Miller (22):
svga: Use proper VGA register name macros in svga_wattr.
svga: Make svga_wattr take an iomem regbase pointer.
svga: Make svga_wcrt_multi take an iomem regbase pointer.
svga: Make svga_wseq_multi take an iomem regbase pointer.
svga: Make svga_set_default_gfx_regs take an iomem regbase pointer.
svga: Make svga_set_default_atc_regs take an iomem regbase pointer.
svga: Make svga_set_default_seq_regs take an iomem regbase pointer.
svga: Make svga_wseq_mask() take an iomem regbase pointer.
svga: Make svga_wcrt_mask() take an iomem regbase pointer.
svga: Make svga_set_default_crt_regs() take an iomem regbase pointer.
svga: Make svga_set_textmode_vga_regs() take an iomem regbase pointer.
svga: Make svga_tilecursor() take an iomem regbase pointer.
svga: Make svga_set_timings() take an iomem regbase pointer.
arkfb: Pass par->state.vgabase to vga_*() calls.
s3fb: Pass par->state.vgabase to vga_*() calls.
vt8623fb: Pass par->state.vgabase to vga_*() calls.
arkfb: Don't clobber par->state.vgabase during open method.
s3fb: Don't clobber par->state.vgabase during open method.
vt8623fb: Don't clobber par->state.vgabase during open method.
s3fb: Compute VGA base iomem pointer explicitly.
arkfb: Compute VGA base iomem pointer explicitly.
vt8623fb: Compute VGA base iomem pointer explicitly.
Heiko Schocher (3):
video, sm501: add I/O functions for use on powerpc
video, sm501: add edid and commandline support
video, sm501: add OF binding to support SM501
Henry Nestler (1):
fbcon: Bugfix soft cursor detection in Tile Blitting
Jani Nikula (1):
OMAP: DSS2: Fix def_disp module param description
Jarkko Nikula (1):
omapfb: Fix linker error in drivers/video/omap/lcd_2430sdp.c
Jean Delvare (1):
radeonfb: Let hwmon driver probe the "monid" I2C bus
Justin P. Mattock (1):
drivers:video:aty:radeon_base Fix typo occationally to occasionally
Kirill A. Shutemov (2):
omap: use list_move() instead of list_del()/list_add() combination
vmlfb: use list_move() instead of list_del()/list_add() combination
Martin Decky (1):
video: Fix EDID macros H_SYNC_WIDTH and H_SYNC_OFFSET
Mayuresh Janorkar (4):
OMAP2PLUS: DSS2: Add OMAP4 Kconfig support
OMAP4: DSS2: Add hwmod device names for OMAP4.
OMAPFB: Adding a check for timings in set_def_mode
OMAP: OMAPFB: Adding help for FB_OMAP_LCD_VGA option
Murthy, Raghuveer (5):
OMAP: DSS2: Adding dss_features for independent core clk divider
OMAP: DSS2: Renaming register macro DISPC_DIVISOR(ch)
OMAP4: DSS2: Using dss_features to set independent core clock divider
OMAP: DSS2: Implement OMAP4 DSS fclk support
OMAP4: PandaBoard: Adding DVI support
Mythri P K (10):
OMAP4: DSS2: Add display type HDMI to DSS2
OMAP4: DSS2: HDMI: Select between HDMI VENC clock source.
OMAP4: DSS2: HDMI: Dispc gamma enable set/reset function for TV.
OMAP4: DSS2: HDMI: HDMI driver header file addition
OMAP4: DSS2: HDMI: HDMI driver addition in the DSS
OMAP4: DSS2: HDMI: HDMI panel driver addition in the DSS
OMAP4: DSS2: HDMI: Add makefile and kconfig changes to enable HDMI in OMAP4
OMAP4: DSS: HDMI: Call to HDMI module init to register driver.
OMAP4: HDMI: Add HDMI structure in the board file for OMAP4 SDP
OMAP4: HDMI: Add HDMI structure in the board file for OMAP4 PANDA
Ondrej Zary (5):
s3fb: maximize virtual vertical size for fast scrolling
s3fb: add support for 86C365 Trio3D
s3fb: fix 15/16bpp modes with over 115MHz pixclocks on 86C365 Trio3D
s3fb: enable DTPC
s3fb: use new start address register
Paul Mundt (4):
mailmap: Update for OMAP DSS developers.
video: Move sm501fb devicetree binding documentation to a better place.
MAINTAINERS: Add file pattern for fb dt bindings.
MAINTAINERS: de-orphan fbdev.
Samreen (1):
OMAP2/3/4: DSS2: Enable Display SubSystem as modules
Senthilvadivu Guruswamy (9):
OMAP2,3: DSS2: Build omap_device for each DSS HWIP
OMAP2, 3: DSS2: DSS: create platform_driver, move init, exit to driver
OMAP2, 3: DSS2: Move clocks from core driver to dss driver
OMAP2, 3: DSS2: RFBI: create platform_driver, move init, exit to driver
OMAP2, 3: DSS2: DISPC: create platform_driver, move init, exit to driver
OMAP2, 3: DSS2: VENC: create platform_driver, move init, exit to driver
OMAP2, 3: DSS2: DSI: create platform_driver, move init, exit to driver
OMAP2,3: DSS2: Use platform device to get baseaddr
OMAP2,3: DSS2: Get DSS IRQ from platform device
Steve Sakoman (5):
OMAP: DSS2: Add support for LG Philips LB035Q02 panel
OMAP: DSS2: Add DSS2 support for Overo
omap: overo: Add regulator for ads7846
OMAP: Add gpio-leds support for Overo
OMAP: Add gpio-keys support for Overo
Sumit Semwal (6):
OMAP2, 3: DSS2: remove forced clk-disable from omap_dss_remove
OMAP2,3: DSS2: replace printk with dev_dbg in init
OMAP2PLUS: clocks: Align DSS clock names and roles
OMAP4: DSS2: clocks: Add ick as dummy clock
OMAP2PLUS:DSS2: add opt_clock_available in pdata
OMAP2PLUS:DSS2: Use opt_clock_available from pdata
Thomas Schlichter (1):
uvesafb,vesafb: create WC or WB PAT-entries
Tomi Valkeinen (25):
OMAP: 3430SDP: Remove unused vdda_dac supply
OMAP: DSS2: Delay regulator_get() calls
OMAP: DSS2: Support for Samsung LTE430WQ-F0C
MAINTAINERS: Update OMAP DSS maintainer
OMAP: DSS2: Clean up a switch-case
OMAP: DSS2: FEATURES: Remove SDI from 3630 displays
OMAP: DSS2: FEATURES: Remove DSI & SDI from OMAP2
OMAP: DSS2: Check for SDI HW before accessing SDI registers
OMAP: DSS2: Remove unused list
OMAP: DSS2: DSI: remove unused function
OMAP: DSS2: Remove FB_OMAP_BOOTLOADER_INIT support
OMAP: DSS2: Remove pdev argument from dpi_init
OMAP: DSS2: Move DPI & SDI init into DSS plat driver
OMAP: DSS2: Remove unneeded cpu_is_xxx checks
HACK: OMAP: DSS2: Fix OMAP2_DSS_USE_DSI_PLL
HACK: OMAP: DSS2: add delay after enabling clocks
OMAP: DSS2: fix omap_dispc_register_isr() fail path
HACK: OMAP: DSS2: VENC: disable VENC on OMAP4 to prevent crash
OMAP: DSS2: DSI: Restructure IRQ handler
OMAP: DSS2: DSI: Add ISR support
OMAP: DSS2: DSI: use ISR in send_bta_sync
OMAP: DSS2: DSI: use ISR for BTA in framedone
OMAP: DSS2: DSI: catch DSI errors in send_bta_sync
OMAP: DSS2: DSI: fix IRQ debug prints
OMAP: DSS2: Clean up for dpll4_m4_ck handling
.mailmap | 4 +
Documentation/devicetree/bindings/fb/sm501fb.txt | 34 +
Documentation/fb/sm501.txt | 10 +
MAINTAINERS | 8 +-
arch/arm/configs/omap2plus_defconfig | 11 +
arch/arm/mach-omap2/board-3430sdp.c | 6 +-
arch/arm/mach-omap2/board-4430sdp.c | 75 ++
arch/arm/mach-omap2/board-cm-t35.c | 2 +-
arch/arm/mach-omap2/board-devkit8000.c | 12 +-
arch/arm/mach-omap2/board-igep0020.c | 10 +-
arch/arm/mach-omap2/board-omap3beagle.c | 12 +-
arch/arm/mach-omap2/board-omap3evm.c | 12 +-
arch/arm/mach-omap2/board-omap3pandora.c | 3 +-
arch/arm/mach-omap2/board-omap3stalker.c | 12 +-
arch/arm/mach-omap2/board-omap4panda.c | 203 +++-
arch/arm/mach-omap2/board-overo.c | 357 +++++-
arch/arm/mach-omap2/board-rx51-peripherals.c | 2 +-
arch/arm/mach-omap2/board-zoom-peripherals.c | 12 +-
arch/arm/mach-omap2/clock2420_data.c | 8 +-
arch/arm/mach-omap2/clock2430_data.c | 8 +-
arch/arm/mach-omap2/clock3xxx_data.c | 14 +-
arch/arm/mach-omap2/clock44xx_data.c | 15 +-
arch/arm/mach-omap2/display.c | 80 ++
arch/arm/mach-omap2/omap_hwmod_2420_data.c | 13 +-
arch/arm/mach-omap2/omap_hwmod_2430_data.c | 12 +-
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 23 +-
arch/arm/plat-omap/include/plat/display.h | 15 +-
drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 2 +-
drivers/mfd/sm501.c | 134 +-
drivers/video/arkfb.c | 160 ++-
drivers/video/atmel_lcdfb.c | 31 +-
drivers/video/aty/radeon_base.c | 2 +-
drivers/video/aty/radeon_i2c.c | 3 +
drivers/video/cg14.c | 1 +
drivers/video/cg6.c | 1 +
drivers/video/console/fbcon.c | 4 +-
drivers/video/console/tileblit.c | 2 +-
drivers/video/edid.h | 4 +-
drivers/video/ffb.c | 2 +-
drivers/video/hecubafb.c | 2 +-
drivers/video/hpfb.c | 6 +-
drivers/video/metronomefb.c | 2 +-
drivers/video/omap/Kconfig | 7 +-
drivers/video/omap/blizzard.c | 3 +-
drivers/video/omap/hwa742.c | 3 +-
drivers/video/omap2/displays/Kconfig | 6 +
drivers/video/omap2/displays/Makefile | 1 +
drivers/video/omap2/displays/panel-generic-dpi.c | 25 +
.../omap2/displays/panel-lgphilips-lb035q02.c | 279 ++++
drivers/video/omap2/displays/panel-taal.c | 123 +-
drivers/video/omap2/dss/Kconfig | 14 +-
drivers/video/omap2/dss/Makefile | 2 +
drivers/video/omap2/dss/core.c | 480 +-------
drivers/video/omap2/dss/dispc.c | 335 ++++--
drivers/video/omap2/dss/display.c | 35 +-
drivers/video/omap2/dss/dpi.c | 45 +-
drivers/video/omap2/dss/dsi.c | 967 +++++++++++----
drivers/video/omap2/dss/dss.c | 763 +++++++++--
drivers/video/omap2/dss/dss.h | 153 ++-
drivers/video/omap2/dss/dss_features.c | 163 ++-
drivers/video/omap2/dss/dss_features.h | 27 +
drivers/video/omap2/dss/hdmi.c | 1332 ++++++++++++++++++++
drivers/video/omap2/dss/hdmi.h | 415 ++++++
drivers/video/omap2/dss/hdmi_omap4_panel.c | 222 ++++
drivers/video/omap2/dss/manager.c | 13 +-
drivers/video/omap2/dss/overlay.c | 10 +-
drivers/video/omap2/dss/rfbi.c | 128 ++-
drivers/video/omap2/dss/sdi.c | 62 +-
drivers/video/omap2/dss/venc.c | 128 ++-
drivers/video/omap2/omapfb/Kconfig | 6 +-
drivers/video/omap2/omapfb/omapfb-main.c | 23 +-
drivers/video/s3c-fb.c | 1 +
drivers/video/s3fb.c | 341 +++--
drivers/video/sh7760fb.c | 4 +-
drivers/video/sh_mobile_lcdcfb.c | 5 +-
drivers/video/sis/sis.h | 1 +
drivers/video/sis/sis_main.c | 315 ++++--
drivers/video/sis/vgatypes.h | 1 +
drivers/video/sm501fb.c | 275 +++--
drivers/video/svgalib.c | 175 ++--
drivers/video/tcx.c | 1 +
drivers/video/uvesafb.c | 49 +-
drivers/video/vermilion/vermilion.c | 3 +-
drivers/video/vesafb.c | 44 +-
drivers/video/vt8623fb.c | 157 ++-
include/linux/sm501.h | 8 +
include/linux/svga.h | 34 +-
include/video/atmel_lcdc.h | 1 +
88 files changed, 6494 insertions(+), 2020 deletions(-)
create mode 100644 Documentation/devicetree/bindings/fb/sm501fb.txt
create mode 100644 Documentation/fb/sm501.txt
create mode 100644 drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
create mode 100644 drivers/video/omap2/dss/hdmi.c
create mode 100644 drivers/video/omap2/dss/hdmi.h
create mode 100644 drivers/video/omap2/dss/hdmi_omap4_panel.c
^ permalink raw reply
* [GIT PULL] viafb fixes for 2.6.39
From: Florian Tobias Schandinat @ 2011-03-23 12:25 UTC (permalink / raw)
To: linux-fbdev
Hi Paul,
please pull the viafb fixes below.
They fix the handling of refresh rates which should now work (or at least work
much better than it did before). Especially the initial refresh rate as passed
in via module parameter is now handled correct. Before these patches this didn't
work for higher refresh rates.
Thanks,
Florian Tobias Schandinat
The following changes since commit 2563afa9ec6970f3545906382cc986ee012f60ec:
Florian Tobias Schandinat (1):
Merge branch 'viafb-pll' into viafb-next
are available in the git repository at:
git://github.com/schandinat/linux-2.6.git viafb-next
Florian Tobias Schandinat (2):
viafb: refresh rate bug collection
viafb: initialize margins correct
drivers/video/via/chip.h | 1 -
drivers/video/via/hw.c | 17 ++++------
drivers/video/via/hw.h | 3 +-
drivers/video/via/viafbdev.c | 74 +++++++++++++++++++++--------------------
4 files changed, 46 insertions(+), 49 deletions(-)
^ permalink raw reply
* Re: [GIT PULL] omap display subsystem changes for 2.6.39
From: Tomi Valkeinen @ 2011-03-23 7:46 UTC (permalink / raw)
To: Felipe Contreras, Tony Lindgren
Cc: Paul Mundt, linux-fbdev@vger.kernel.org,
linux-omap@vger.kernel.org
In-Reply-To: <AANLkTimSoaxGhjbgMx6b3duAV75HwO0S+=1mJhOnEvvD@mail.gmail.com>
On Tue, 2011-03-22 at 13:49 -0500, Felipe Contreras wrote:
> On Mon, Mar 21, 2011 at 11:51 AM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote:
> > Here are OMAP display subsystem patches for 2.6.39 merge window. Quite a
> > bit of them, and many changes also in arch/arm/mach-omap2, which
> > unfortunately couldn't go through Tony's linux-omap tree due to
> > dependencies on DSS driver code.
>
> What about this one?
> http://article.gmane.org/gmane.linux.ports.arm.omap/44975
I seem to have missed that one. But I think that should go through
Tony's tree to avoid conflicts. Tony?
Acked-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Tomi
^ permalink raw reply
* Re: [RFC PATCH] HDMI:Support for EDID parsing in kernel.
From: Dave Airlie @ 2011-03-23 0:46 UTC (permalink / raw)
To: Mythri P K; +Cc: linux-fbdev, linux-omap, linux-media, dri-devel
In-Reply-To: <1300815176-21206-1-git-send-email-mythripk@ti.com>
On Wed, Mar 23, 2011 at 3:32 AM, Mythri P K <mythripk@ti.com> wrote:
> Adding support for common EDID parsing in kernel.
>
> EDID - Extended display identification data is a data structure provided by
> a digital display to describe its capabilities to a video source, This a
> standard supported by CEA and VESA.
>
> There are several custom implementations for parsing EDID in kernel, some
> of them are present in fbmon.c, drm_edid.c, sh_mobile_hdmi.c, Ideally
> parsing of EDID should be done in a library, which is agnostic of the
> framework (V4l2, DRM, FB) which is using the functionality, just based on
> the raw EDID pointer with size/segment information.
>
> With other RFC's such as the one below, which tries to standardize HDMI API's
> It would be better to have a common EDID code in one place.It also helps to
> provide better interoperability with variety of TV/Monitor may be even by
> listing out quirks which might get missed with several custom implementation
> of EDID.
> http://permalink.gmane.org/gmane.linux.drivers.video-input-infrastructure/30401
>
> This patch tries to add functions to parse some portion EDID (detailed timing,
> monitor limits, AV delay information, deep color mode support, Audio and VSDB)
> If we can align on this library approach i can enhance this library to parse
> other blocks and probably we could also add quirks from other implementation
> as well.
>
If you want to take this approach, you need to start from the DRM EDID parser,
its the most well tested and I can guarantee its been plugged into more monitors
than any of the others. There is just no way we would move the DRM parser to a
library one that isn't derived from it + enhancements, as we'd throw away the
years of testing and the regression count would be way too high.
Dave.
^ permalink raw reply
* Re: [PATCH v6 0/6] powerpc, 52xx: add charon board support
From: Grant Likely @ 2011-03-22 20:58 UTC (permalink / raw)
To: Heiko Schocher
Cc: linuxppc-dev, Wolfram Sang, Benjamin Herrenschmidt, linux-fbdev,
devicetree-discuss, Ben Dooks, Vincent Sanders, Samuel Ortiz,
linux-kernel, Randy Dunlap, Wolfgang Denk, Paul Mundt
In-Reply-To: <1300782452-528-1-git-send-email-hs@denx.de>
On Tue, Mar 22, 2011 at 2:27 AM, Heiko Schocher <hs@denx.de> wrote:
> cc: Wolfram Sang <w.sang@pengutronix.de>
> cc: Grant Likely <grant.likely@secretlab.ca>
> cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> cc: linux-fbdev@vger.kernel.org
> cc: devicetree-discuss@ozlabs.org
> cc: Ben Dooks <ben@simtec.co.uk>
> cc: Vincent Sanders <vince@simtec.co.uk>
> cc: Samuel Ortiz <sameo@linux.intel.com>
> cc: linux-kernel@vger.kernel.org
> cc: Randy Dunlap <rdunlap@xenotime.net>
> cc: Wolfgang Denk <wd@denx.de>
> cc: Paul Mundt <lethal@linux-sh.org>
>
> changes since v5:
> - repost complete patchseries, as Paul Mundt suggested
> - rebased against current head
> - add Acked-by from Samuel Ortiz (MFD parts)
> http://www.spinics.net/lists/linux-fbdev/msg02550.html
> http://linux.derkeiler.com/Mailing-Lists/Kernel/2011-01/msg11798.html
>
> and Benjamin Herrenschmidt (DTS parts)
> http://lists.ozlabs.org/pipermail/linuxppc-dev/2011-February/088279.html
> - removed patch
> "powerpc, mpc5200: update mpc5200_defconfig to fit for charon board."
> therefore added
> "powerpc, tqm5200: update tqm5200_defconfig to fit for charon board."
Why? As Wolfram mentioned, I'd rather see mpc5200 defconfig used.
Eventually I'd like to remove tqm5200_defconfig
I'll look through the rest of the patches soon.
g.
^ permalink raw reply
* Re: [GIT PULL] omap display subsystem changes for 2.6.39
From: Felipe Contreras @ 2011-03-22 18:49 UTC (permalink / raw)
To: Tomi Valkeinen; +Cc: Paul Mundt, linux-fbdev, linux-omap
In-Reply-To: <1300701083.2891.77.camel@deskari>
On Mon, Mar 21, 2011 at 11:51 AM, Tomi Valkeinen <tomi.valkeinen@ti.com> wrote:
> Here are OMAP display subsystem patches for 2.6.39 merge window. Quite a
> bit of them, and many changes also in arch/arm/mach-omap2, which
> unfortunately couldn't go through Tony's linux-omap tree due to
> dependencies on DSS driver code.
What about this one?
http://article.gmane.org/gmane.linux.ports.arm.omap/44975
--
Felipe Contreras
^ permalink raw reply
* Re: [RFC PATCH] HDMI:Support for EDID parsing in kernel.
From: Alex Deucher @ 2011-03-22 18:32 UTC (permalink / raw)
To: Mythri P K
Cc: linux-fbdev, linux-omap, linux-media,
Maling list - DRI developers
In-Reply-To: <1300815176-21206-1-git-send-email-mythripk@ti.com>
Adding dri-devel.
On Tue, Mar 22, 2011 at 1:32 PM, Mythri P K <mythripk@ti.com> wrote:
> Adding support for common EDID parsing in kernel.
>
> EDID - Extended display identification data is a data structure provided by
> a digital display to describe its capabilities to a video source, This a
> standard supported by CEA and VESA.
>
> There are several custom implementations for parsing EDID in kernel, some
> of them are present in fbmon.c, drm_edid.c, sh_mobile_hdmi.c, Ideally
> parsing of EDID should be done in a library, which is agnostic of the
> framework (V4l2, DRM, FB) which is using the functionality, just based on
> the raw EDID pointer with size/segment information.
>
> With other RFC's such as the one below, which tries to standardize HDMI API's
> It would be better to have a common EDID code in one place.It also helps to
> provide better interoperability with variety of TV/Monitor may be even by
> listing out quirks which might get missed with several custom implementation
> of EDID.
> http://permalink.gmane.org/gmane.linux.drivers.video-input-infrastructure/30401
>
> This patch tries to add functions to parse some portion EDID (detailed timing,
> monitor limits, AV delay information, deep color mode support, Audio and VSDB)
> If we can align on this library approach i can enhance this library to parse
> other blocks and probably we could also add quirks from other implementation
> as well.
>
> Signed-off-by: Mythri P K <mythripk@ti.com>
> ---
> arch/arm/include/asm/edid.h | 243 ++++++++++++++++++++++++++++++
> drivers/video/edid.c | 340 +++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 583 insertions(+), 0 deletions(-)
> create mode 100644 arch/arm/include/asm/edid.h
> create mode 100644 drivers/video/edid.c
>
> diff --git a/arch/arm/include/asm/edid.h b/arch/arm/include/asm/edid.h
> new file mode 100644
> index 0000000..843346a
> --- /dev/null
> +++ b/arch/arm/include/asm/edid.h
> @@ -0,0 +1,243 @@
> +/*
> + * edid.h
> + *
> + * Copyright (C) 2011 Texas Instruments
> + * Author: Mythri P K <mythripk@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/>.
> + * History:
> + */
> +
> +#ifndef _EDID_H_
> +#define _EDID_H_
> +
> +/* HDMI EDID Length */
> +#define HDMI_EDID_MAX_LENGTH 512
> +
> +/* HDMI EDID Extension Data Block Tags */
> +#define HDMI_EDID_EX_DATABLOCK_TAG_MASK 0xE0
> +#define HDMI_EDID_EX_DATABLOCK_LEN_MASK 0x1F
> +
> +#define EDID_TIMING_DESCRIPTOR_SIZE 0x12
> +#define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36
> +#define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80
> +#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4
> +#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4
> +
> +/* EDID Detailed Timing Info 0 begin offset */
> +#define HDMI_EDID_DETAILED_TIMING_OFFSET 0x36
> +
> +#define HDMI_EDID_PIX_CLK_OFFSET 0
> +#define HDMI_EDID_H_ACTIVE_OFFSET 2
> +#define HDMI_EDID_H_BLANKING_OFFSET 3
> +#define HDMI_EDID_V_ACTIVE_OFFSET 5
> +#define HDMI_EDID_V_BLANKING_OFFSET 6
> +#define HDMI_EDID_H_SYNC_OFFSET 8
> +#define HDMI_EDID_H_SYNC_PW_OFFSET 9
> +#define HDMI_EDID_V_SYNC_OFFSET 10
> +#define HDMI_EDID_V_SYNC_PW_OFFSET 11
> +#define HDMI_EDID_H_IMAGE_SIZE_OFFSET 12
> +#define HDMI_EDID_V_IMAGE_SIZE_OFFSET 13
> +#define HDMI_EDID_H_BORDER_OFFSET 15
> +#define HDMI_EDID_V_BORDER_OFFSET 16
> +#define HDMI_EDID_FLAGS_OFFSET 17
> +
> +/* HDMI EDID DTDs */
> +#define HDMI_EDID_MAX_DTDS 4
> +
> +/* HDMI EDID DTD Tags */
> +#define HDMI_EDID_DTD_TAG_MONITOR_NAME 0xFC
> +#define HDMI_EDID_DTD_TAG_MONITOR_SERIALNUM 0xFF
> +#define HDMI_EDID_DTD_TAG_MONITOR_LIMITS 0xFD
> +#define HDMI_EDID_DTD_TAG_STANDARD_TIMING_DATA 0xFA
> +#define HDMI_EDID_DTD_TAG_COLOR_POINT_DATA 0xFB
> +#define HDMI_EDID_DTD_TAG_ASCII_STRING 0xFE
> +
> +#define HDMI_IMG_FORMAT_MAX_LENGTH 20
> +#define HDMI_AUDIO_FORMAT_MAX_LENGTH 10
> +
> +/* HDMI EDID Extenion Data Block Values: Video */
> +#define HDMI_EDID_EX_VIDEO_NATIVE 0x80
> +#define HDMI_EDID_EX_VIDEO_MASK 0x7F
> +#define HDMI_EDID_EX_VIDEO_MAX 35
> +
> +#define STANDARD_HDMI_TIMINGS_NB 34
> +#define STANDARD_HDMI_TIMINGS_VESA_START 15
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +enum extension_edid_db {
> + DATABLOCK_AUDIO = 1,
> + DATABLOCK_VIDEO = 2,
> + DATABLOCK_VENDOR = 3,
> + DATABLOCK_SPEAKERS = 4,
> +};
> +
> +struct img_edid {
> + bool pref;
> + int code;
> +};
> +
> +struct image_format {
> + int length;
> + struct img_edid fmt[HDMI_IMG_FORMAT_MAX_LENGTH];
> +};
> +
> +struct audio_edid {
> + int num_of_ch;
> + int format;
> +};
> +
> +struct audio_format {
> + int length;
> + struct audio_edid fmt[HDMI_AUDIO_FORMAT_MAX_LENGTH];
> +};
> +
> +struct latency {
> + /* vid: if indicated, value=1+ms/2 with a max of 251 meaning 500ms */
> + int vid_latency;
> + int aud_latency;
> + int int_vid_latency;
> + int int_aud_latency;
> +};
> +
> +struct deep_color {
> + bool bit_30;
> + bool bit_36;
> + int max_tmds_freq;
> +};
> +
> +/* Video Descriptor Block */
> +struct HDMI_EDID_DTD_VIDEO {
> + u16 pixel_clock; /* 54-55 */
> + u8 horiz_active; /* 56 */
> + u8 horiz_blanking; /* 57 */
> + u8 horiz_high; /* 58 */
> + u8 vert_active; /* 59 */
> + u8 vert_blanking; /* 60 */
> + u8 vert_high; /* 61 */
> + u8 horiz_sync_offset; /* 62 */
> + u8 horiz_sync_pulse; /* 63 */
> + u8 vert_sync_pulse; /* 64 */
> + u8 sync_pulse_high; /* 65 */
> + u8 horiz_image_size; /* 66 */
> + u8 vert_image_size; /* 67 */
> + u8 image_size_high; /* 68 */
> + u8 horiz_border; /* 69 */
> + u8 vert_border; /* 70 */
> + u8 misc_settings; /* 71 */
> +};
> +
> +/* Monitor Limits Descriptor Block */
> +struct HDMI_EDID_DTD_MONITOR {
> + u16 pixel_clock; /* 54-55*/
> + u8 _reserved1; /* 56 */
> + u8 block_type; /* 57 */
> + u8 _reserved2; /* 58 */
> + u8 min_vert_freq; /* 59 */
> + u8 max_vert_freq; /* 60 */
> + u8 min_horiz_freq; /* 61 */
> + u8 max_horiz_freq; /* 62 */
> + u8 pixel_clock_mhz; /* 63 */
> + u8 GTF[2]; /* 64 -65 */
> + u8 start_horiz_freq; /* 66 */
> + u8 C; /* 67 */
> + u8 M[2]; /* 68-69 */
> + u8 K; /* 70 */
> + u8 J; /* 71 */
> +
> +} __packed;
> +
> +/* Text Descriptor Block */
> +struct HDMI_EDID_DTD_TEXT {
> + u16 pixel_clock; /* 54-55 */
> + u8 _reserved1; /* 56 */
> + u8 block_type; /* 57 */
> + u8 _reserved2; /* 58 */
> + u8 text[13]; /* 59-71 */
> +} __packed;
> +
> +/* DTD Union */
> +union HDMI_EDID_DTD {
> + struct HDMI_EDID_DTD_VIDEO video;
> + struct HDMI_EDID_DTD_TEXT monitor_name;
> + struct HDMI_EDID_DTD_TEXT monitor_serial_number;
> + struct HDMI_EDID_DTD_TEXT ascii;
> + struct HDMI_EDID_DTD_MONITOR monitor_limits;
> +} __packed;
> +
> +/* EDID struct */
> +struct HDMI_EDID {
> + u8 header[8]; /* 00-07 */
> + u16 manufacturerID; /* 08-09 */
> + u16 product_id; /* 10-11 */
> + u32 serial_number; /* 12-15 */
> + u8 week_manufactured; /* 16 */
> + u8 year_manufactured; /* 17 */
> + u8 edid_version; /* 18 */
> + u8 edid_revision; /* 19 */
> + u8 video_in_definition; /* 20 */
> + u8 max_horiz_image_size; /* 21 */
> + u8 max_vert_image_size; /* 22 */
> + u8 display_gamma; /* 23 */
> + u8 power_features; /* 24 */
> + u8 chroma_info[10]; /* 25-34 */
> + u8 timing_1; /* 35 */
> + u8 timing_2; /* 36 */
> + u8 timing_3; /* 37 */
> + u8 std_timings[16]; /* 38-53 */
> + union HDMI_EDID_DTD DTD[4]; /* 54-125 */
> + u8 extension_edid; /* 126 */
> + u8 checksum; /* 127 */
> + u8 extension_tag; /* 00 (extensions follow EDID) */
> + u8 extention_rev; /* 01 */
> + u8 offset_dtd; /* 02 */
> + u8 num_dtd; /* 03 */
> + u8 data_block[123]; /* 04 - 126 */
> + u8 extension_checksum; /* 127 */
> +
> + u8 ext_datablock[256];
> +} __packed;
> +
> +struct hdmi_timings {
> +
> + u16 x_res;
> + u16 y_res;
> + u32 pixel_clock; /* pixel clock in KHz */
> + u16 hsw; /* Horizontal synchronization pulse width */
> + u16 hfp; /* Horizontal front porch */
> + u16 hbp; /* Horizontal back porch */
> + u16 vsw; /* Vertical synchronization pulse width */
> + u16 vfp; /* Vertical front porch */
> + u16 vbp; /* Vertical back porch */
> +};
> +
> +int get_edid_timing_info(union HDMI_EDID_DTD *edid_dtd,
> + struct hdmi_timings *timings);
> +void get_eedid_timing_info(int current_descriptor_addrs, u8 *edid ,
> + struct hdmi_timings *timings);
> +int hdmi_get_datablock_offset(u8 *edid, enum extension_edid_db datablock,
> + int *offset);
> +int hdmi_get_image_format(u8 *edid, struct image_format *format);
> +int hdmi_get_audio_format(u8 *edid, struct audio_format *format);
> +void hdmi_get_av_delay(u8 *edid, struct latency *lat);
> +void hdmi_deep_color_support_info(u8 *edid, struct deep_color *format);
> +bool hdmi_tv_yuv_supported(u8 *edid);
> +
> +#ifdef __cplusplus
> +};
> +#endif
> +
> +#endif
> diff --git a/drivers/video/edid.c b/drivers/video/edid.c
> new file mode 100644
> index 0000000..4eb2074
> --- /dev/null
> +++ b/drivers/video/edid.c
> @@ -0,0 +1,340 @@
> +/*
> + * edid.c
> + *
> + * Copyright (C) 2011 Texas Instruments
> + * Author: Mythri P K <mythripk@ti.com>
> + * With EDID parsing for DVI Monitor from Rob Clark <rob@ti.com>
> + *
> + * EDID.c to parse the EDID content.
> + *
> + * 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/>.
> + * History:
> + *
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/err.h>
> +#include <linux/string.h>
> +#include <linux/slab.h>
> +#include <asm/edid.h>
> +
> +/* Standard HDMI/VESA timings */
> +const struct hdmi_timings standard_hdmi_timings[STANDARD_HDMI_TIMINGS_NB] = {
> + {640, 480, 25200, 96, 16, 48, 2, 10, 33},
> + {1280, 720, 74250, 40, 440, 220, 5, 5, 20},
> + {1280, 720, 74250, 40, 110, 220, 5, 5, 20},
> + {720, 480, 27027, 62, 16, 60, 6, 9, 30},
> + {2880, 576, 108000, 256, 48, 272, 5, 5, 39},
> + {1440, 240, 27027, 124, 38, 114, 3, 4, 15},
> + {1440, 288, 27000, 126, 24, 138, 3, 2, 19},
> + {1920, 540, 74250, 44, 528, 148, 5, 2, 15},
> + {1920, 540, 74250, 44, 88, 148, 5, 2, 15},
> + {1920, 1080, 148500, 44, 88, 148, 5, 4, 36},
> + {720, 576, 27000, 64, 12, 68, 5, 5, 39},
> + {1440, 576, 54000, 128, 24, 136, 5, 5, 39},
> + {1920, 1080, 148500, 44, 528, 148, 5, 4, 36},
> + {2880, 480, 108108, 248, 64, 240, 6, 9, 30},
> + {1920, 1080, 74250, 44, 638, 148, 5, 4, 36},
> + /* Vesa frome here */
> + {640, 480, 25175, 96, 16, 48, 2 , 11, 31},
> + {800, 600, 40000, 128, 40, 88, 4 , 1, 23},
> + {848, 480, 33750, 112, 16, 112, 8 , 6, 23},
> + {1280, 768, 79500, 128, 64, 192, 7 , 3, 20},
> + {1280, 800, 83500, 128, 72, 200, 6 , 3, 22},
> + {1360, 768, 85500, 112, 64, 256, 6 , 3, 18},
> + {1280, 960, 108000, 112, 96, 312, 3 , 1, 36},
> + {1280, 1024, 108000, 112, 48, 248, 3 , 1, 38},
> + {1024, 768, 65000, 136, 24, 160, 6, 3, 29},
> + {1400, 1050, 121750, 144, 88, 232, 4, 3, 32},
> + {1440, 900, 106500, 152, 80, 232, 6, 3, 25},
> + {1680, 1050, 146250, 176 , 104, 280, 6, 3, 30},
> + {1366, 768, 85500, 143, 70, 213, 3, 3, 24},
> + {1920, 1080, 148500, 44, 88, 80, 5, 4, 36},
> + {1280, 768, 68250, 32, 48, 80, 7, 3, 12},
> + {1400, 1050, 101000, 32, 48, 80, 4, 3, 23},
> + {1680, 1050, 119000, 32, 48, 80, 6, 3, 21},
> + {1280, 800, 79500, 32, 48, 80, 6, 3, 14},
> + {1280, 720, 74250, 40, 110, 220, 5, 5, 20}
> +};
> +
> +int get_edid_timing_info(union HDMI_EDID_DTD *edid_dtd,
> + struct hdmi_timings *timings)
> +{
> + if (edid_dtd->video.pixel_clock) {
> + struct HDMI_EDID_DTD_VIDEO *vid = &edid_dtd->video;
> +
> + timings->pixel_clock = 10 * vid->pixel_clock;
> + timings->x_res = vid->horiz_active |
> + (((u16)vid->horiz_high & 0xf0) << 4);
> + timings->y_res = vid->vert_active |
> + (((u16)vid->vert_high & 0xf0) << 4);
> + timings->hfp = vid->horiz_sync_offset |
> + (((u16)vid->sync_pulse_high & 0xc0) << 2);
> + timings->hsw = vid->horiz_sync_pulse |
> + (((u16)vid->sync_pulse_high & 0x30) << 4);
> + timings->hbp = (vid->horiz_blanking |
> + (((u16)vid->horiz_high & 0x0f) << 8)) -
> + (timings->hfp + timings->hsw);
> + timings->vfp = ((vid->vert_sync_pulse & 0xf0) >> 4) |
> + ((vid->sync_pulse_high & 0x0f) << 2);
> + timings->vsw = (vid->vert_sync_pulse & 0x0f) |
> + ((vid->sync_pulse_high & 0x03) << 4);
> + timings->vbp = (vid->vert_blanking |
> + (((u16)vid->vert_high & 0x0f) << 8)) -
> + (timings->vfp + timings->vsw);
> + return 0;
> + }
> +
> + switch (edid_dtd->monitor_name.block_type) {
> + case HDMI_EDID_DTD_TAG_STANDARD_TIMING_DATA:
> + printk(KERN_INFO "standard timing data\n");
> + return -EINVAL;
> + case HDMI_EDID_DTD_TAG_COLOR_POINT_DATA:
> + printk(KERN_INFO "color point data\n");
> + return -EINVAL;
> + case HDMI_EDID_DTD_TAG_MONITOR_NAME:
> + printk(KERN_INFO "monitor name: %s\n",
> + edid_dtd->monitor_name.text);
> + return -EINVAL;
> + case HDMI_EDID_DTD_TAG_MONITOR_LIMITS:
> + {
> + int i, max_area = 0, best_idx = -1;
> + struct HDMI_EDID_DTD_MONITOR *limits > + &edid_dtd->monitor_limits;
> +
> + printk(KERN_DEBUG " monitor limits\n");
> + printk(KERN_DEBUG " min_vert_freq=%d\n",
> + limits->min_vert_freq);
> + printk(KERN_DEBUG " max_vert_freq=%d\n",
> + limits->max_vert_freq);
> + printk(KERN_DEBUG " min_horiz_freq=%d\n",
> + limits->min_horiz_freq);
> + printk(KERN_DEBUG " max_horiz_freq=%d\n",
> + limits->max_horiz_freq);
> + printk(KERN_DEBUG " pixel_clock_mhz=%d\n",
> + limits->pixel_clock_mhz * 10);
> +
> + /* find the highest matching resolution (w*h) */
> +
> + /*
> + * XXX since this is mainly for DVI monitors, should we only
> + * support VESA timings? My monitor at home would pick
> + * 1920x1080 otherwise, but that seems to not work well (monitor
> + * blanks out and comes back, and picture doesn't fill full
> + * screen, but leaves a black bar on left (native res is
> + * 2048x1152). However if I only consider VESA timings, it picks
> + * 1680x1050 and the picture is stable and fills whole screen
> + */
> + for (i = STANDARD_HDMI_TIMINGS_VESA_START;
> + i < STANDARD_HDMI_TIMINGS_NB; i++) {
> + const struct hdmi_timings *timings > + &standard_hdmi_timings[i];
> + int hz, hscan, pixclock;
> + int vtotal, htotal;
> + htotal = timings->hbp + timings->hfp +
> + timings->hsw + timings->x_res;
> + vtotal = timings->vbp + timings->vfp +
> + timings->vsw + timings->y_res;
> +
> + /* NOTE: We don't support interlaced mode for VESA */
> + pixclock = timings->pixel_clock * 1000;
> + hscan = (pixclock + htotal / 2) / htotal;
> + hscan = (hscan + 500) / 1000 * 1000;
> + hz = (hscan + vtotal / 2) / vtotal;
> + hscan /= 1000;
> + pixclock /= 1000000;
> + if ((pixclock < (limits->pixel_clock_mhz * 10)) &&
> + (limits->min_horiz_freq <= hscan) &&
> + (hscan <= limits->max_horiz_freq) &&
> + (limits->min_vert_freq <= hz) &&
> + (hz <= limits->max_vert_freq)) {
> + int area = timings->x_res * timings->y_res;
> + printk(KERN_INFO " -> %d: %dx%d\n", i,
> + timings->x_res, timings->y_res);
> + if (area > max_area) {
> + max_area = area;
> + best_idx = i;
> + }
> + }
> + }
> + if (best_idx > 0) {
> + *timings = standard_hdmi_timings[best_idx];
> + printk(KERN_DEBUG "found best resolution: %dx%d (%d)\n",
> + timings->x_res, timings->y_res, best_idx);
> + }
> + return 0;
> + }
> + case HDMI_EDID_DTD_TAG_ASCII_STRING:
> + printk(KERN_INFO "ascii string: %s\n", edid_dtd->ascii.text);
> + return -EINVAL;
> + case HDMI_EDID_DTD_TAG_MONITOR_SERIALNUM:
> + printk(KERN_INFO "monitor serialnum: %s\n",
> + edid_dtd->monitor_serial_number.text);
> + return -EINVAL;
> + default:
> + printk(KERN_INFO "unsupported EDID descriptor block format\n");
> + return -EINVAL;
> + }
> +}
> +
> +void get_eedid_timing_info(int current_descriptor_addrs, u8 *edid ,
> + struct hdmi_timings *timings)
> +{
> + timings->x_res = (((edid[current_descriptor_addrs + 4] & 0xF0) << 4)
> + | edid[current_descriptor_addrs + 2]);
> + timings->y_res = (((edid[current_descriptor_addrs + 7] & 0xF0) << 4)
> + | edid[current_descriptor_addrs + 5]);
> + timings->pixel_clock = ((edid[current_descriptor_addrs + 1] << 8)
> + | edid[current_descriptor_addrs]);
> + timings->pixel_clock = 10 * timings->pixel_clock;
> + timings->hfp = edid[current_descriptor_addrs + 8];
> + timings->hsw = edid[current_descriptor_addrs + 9];
> + timings->hbp = (((edid[current_descriptor_addrs + 4] & 0x0F) << 8)
> + | edid[current_descriptor_addrs + 3]) -
> + (timings->hfp + timings->hsw);
> + timings->vfp = ((edid[current_descriptor_addrs + 10] & 0xF0) >> 4);
> + timings->vsw = (edid[current_descriptor_addrs + 10] & 0x0F);
> + timings->vbp = (((edid[current_descriptor_addrs + 7] & 0x0F) << 8)
> + | edid[current_descriptor_addrs + 6]) -
> + (timings->vfp + timings->vsw);
> +}
> +
> +int hdmi_get_datablock_offset(u8 *edid, enum extension_edid_db datablock,
> + int *offset)
> +{
> + int current_byte, disp, i = 0, length = 0;
> +
> + if (edid[0x7e] = 0x00)
> + return -EINVAL;
> +
> + disp = edid[(0x80) + 2];
> + if (disp = 0x4)
> + return -EINVAL;
> +
> + i = 0x80 + 0x4;
> + printk(KERN_INFO "%x\n", i);
> + while (i < (0x80 + disp)) {
> + current_byte = edid[i];
> + if ((current_byte >> 5) = datablock) {
> + *offset = i;
> + printk(KERN_INFO "datablock %d %d\n",
> + datablock, *offset);
> + return 0;
> + } else {
> + length = (current_byte &
> + HDMI_EDID_EX_DATABLOCK_LEN_MASK) + 1;
> + i += length;
> + }
> + }
> + return -EINVAL;
> +}
> +
> +int hdmi_get_image_format(u8 *edid, struct image_format *format)
> +{
> + int offset, current_byte, j = 0, length = 0;
> + enum extension_edid_db vsdb = DATABLOCK_VIDEO;
> + format->length = 0;
> +
> + memset(format->fmt, 0, sizeof(format->fmt));
> + if (!hdmi_get_datablock_offset(edid, vsdb, &offset)) {
> + current_byte = edid[offset];
> + length = current_byte & HDMI_EDID_EX_DATABLOCK_LEN_MASK;
> +
> + if (length >= HDMI_IMG_FORMAT_MAX_LENGTH)
> + format->length = HDMI_IMG_FORMAT_MAX_LENGTH;
> + else
> + format->length = length;
> +
> + for (j = 1 ; j < length ; j++) {
> + current_byte = edid[offset+j];
> + format->fmt[j-1].code = current_byte & 0x7F;
> + format->fmt[j-1].pref = current_byte & 0x80;
> + }
> + }
> + return 0;
> +}
> +
> +int hdmi_get_audio_format(u8 *edid, struct audio_format *format)
> +{
> + int offset, current_byte, j = 0, length = 0;
> + enum extension_edid_db vsdb = DATABLOCK_AUDIO;
> +
> + format->length = 0;
> + memset(format->fmt, 0, sizeof(format->fmt));
> +
> + if (!hdmi_get_datablock_offset(edid, vsdb, &offset)) {
> + current_byte = edid[offset];
> + length = current_byte & HDMI_EDID_EX_DATABLOCK_LEN_MASK;
> +
> + if (length >= HDMI_AUDIO_FORMAT_MAX_LENGTH)
> + format->length = HDMI_AUDIO_FORMAT_MAX_LENGTH;
> + else
> + format->length = length;
> +
> + for (j = 1 ; j < length ; j++) {
> + if (j%3 = 1) {
> + current_byte = edid[offset + j];
> + format->fmt[j-1].format = current_byte & 0x78;
> + format->fmt[j-1].num_of_ch > + (current_byte & 0x07) + 1;
> + }
> + }
> + }
> + return 0;
> +}
> +
> +void hdmi_get_av_delay(u8 *edid, struct latency *lat)
> +{
> + int offset, current_byte, length = 0;
> + enum extension_edid_db vsdb = DATABLOCK_VENDOR;
> +
> + if (!hdmi_get_datablock_offset(edid, vsdb, &offset)) {
> + current_byte = edid[offset];
> + length = current_byte & HDMI_EDID_EX_DATABLOCK_LEN_MASK;
> + if (length >= 8 && ((current_byte + 8) & 0x80)) {
> + lat->vid_latency = (edid[offset + 8] - 1) * 2;
> + lat->aud_latency = (edid[offset + 9] - 1) * 2;
> + }
> + if (length >= 8 && ((current_byte + 8) & 0xC0)) {
> + lat->int_vid_latency = (edid[offset + 10] - 1) * 2;
> + lat->int_aud_latency = (edid[offset + 11] - 1) * 2;
> + }
> + }
> +}
> +
> +void hdmi_deep_color_support_info(u8 *edid, struct deep_color *format)
> +{
> + int offset, current_byte, length = 0;
> + enum extension_edid_db vsdb = DATABLOCK_VENDOR;
> + memset(format, 0, sizeof(*format));
> +
> + if (!hdmi_get_datablock_offset(edid, vsdb, &offset)) {
> + current_byte = edid[offset];
> + length = current_byte & HDMI_EDID_EX_DATABLOCK_LEN_MASK;
> + if (length >= 6) {
> + format->bit_30 = (edid[offset + 6] & 0x10);
> + format->bit_36 = (edid[offset + 6] & 0x20);
> + }
> + if (length >= 7)
> + format->max_tmds_freq = (edid[offset + 7]) * 5;
> + }
> +}
> +
> +bool hdmi_tv_yuv_supported(u8 *edid)
> +{
> + if (edid[0x7e] != 0x00 && edid[0x83] & 0x30) {
> + printk(KERN_INFO "YUV supported");
> + return true;
> + }
> + return false;
> +}
> --
> 1.5.6.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* Re: [RFC PATCH] HDMI:Support for EDID parsing in kernel.
From: Paul Mundt @ 2011-03-22 17:58 UTC (permalink / raw)
To: Mauro Carvalho Chehab; +Cc: Mythri P K, linux-fbdev, linux-omap, linux-media
In-Reply-To: <4D88E1FB.5070503@redhat.com>
On Tue, Mar 22, 2011 at 02:52:59PM -0300, Mauro Carvalho Chehab wrote:
> Em 22-03-2011 14:32, Mythri P K escreveu:
> > Adding support for common EDID parsing in kernel.
> >
> > EDID - Extended display identification data is a data structure provided by
> > a digital display to describe its capabilities to a video source, This a
> > standard supported by CEA and VESA.
> >
> > There are several custom implementations for parsing EDID in kernel, some
> > of them are present in fbmon.c, drm_edid.c, sh_mobile_hdmi.c, Ideally
> > parsing of EDID should be done in a library, which is agnostic of the
> > framework (V4l2, DRM, FB) which is using the functionality, just based on
> > the raw EDID pointer with size/segment information.
> >
> > With other RFC's such as the one below, which tries to standardize HDMI API's
> > It would be better to have a common EDID code in one place.It also helps to
> > provide better interoperability with variety of TV/Monitor may be even by
> > listing out quirks which might get missed with several custom implementation
> > of EDID.
> > http://permalink.gmane.org/gmane.linux.drivers.video-input-infrastructure/30401
> >
> > This patch tries to add functions to parse some portion EDID (detailed timing,
> > monitor limits, AV delay information, deep color mode support, Audio and VSDB)
> > If we can align on this library approach i can enhance this library to parse
> > other blocks and probably we could also add quirks from other implementation
> > as well.
> >
> > Signed-off-by: Mythri P K <mythripk@ti.com>
> > ---
> > arch/arm/include/asm/edid.h | 243 ++++++++++++++++++++++++++++++
> > drivers/video/edid.c | 340 +++++++++++++++++++++++++++++++++++++++++++
>
> Hmm... if you want this to be agnostic, the header file should not be inside
> arch/arm, but on some other place, like include/video/.
>
Ironically this adds a drivers/video/edid.c but completely ignores
drivers/video/edid.h which already exists and already contains many of
these definitions.
I like the idea of a generalized library, but it would be nice to see the
existing edid.h evolved and its users updated incrementally.
^ permalink raw reply
* Re: [RFC PATCH] HDMI:Support for EDID parsing in kernel.
From: Mauro Carvalho Chehab @ 2011-03-22 17:52 UTC (permalink / raw)
To: Mythri P K; +Cc: linux-fbdev, linux-omap, linux-media
In-Reply-To: <1300815176-21206-1-git-send-email-mythripk@ti.com>
Em 22-03-2011 14:32, Mythri P K escreveu:
> Adding support for common EDID parsing in kernel.
>
> EDID - Extended display identification data is a data structure provided by
> a digital display to describe its capabilities to a video source, This a
> standard supported by CEA and VESA.
>
> There are several custom implementations for parsing EDID in kernel, some
> of them are present in fbmon.c, drm_edid.c, sh_mobile_hdmi.c, Ideally
> parsing of EDID should be done in a library, which is agnostic of the
> framework (V4l2, DRM, FB) which is using the functionality, just based on
> the raw EDID pointer with size/segment information.
>
> With other RFC's such as the one below, which tries to standardize HDMI API's
> It would be better to have a common EDID code in one place.It also helps to
> provide better interoperability with variety of TV/Monitor may be even by
> listing out quirks which might get missed with several custom implementation
> of EDID.
> http://permalink.gmane.org/gmane.linux.drivers.video-input-infrastructure/30401
>
> This patch tries to add functions to parse some portion EDID (detailed timing,
> monitor limits, AV delay information, deep color mode support, Audio and VSDB)
> If we can align on this library approach i can enhance this library to parse
> other blocks and probably we could also add quirks from other implementation
> as well.
>
> Signed-off-by: Mythri P K <mythripk@ti.com>
> ---
> arch/arm/include/asm/edid.h | 243 ++++++++++++++++++++++++++++++
> drivers/video/edid.c | 340 +++++++++++++++++++++++++++++++++++++++++++
Hmm... if you want this to be agnostic, the header file should not be inside
arch/arm, but on some other place, like include/video/.
> 2 files changed, 583 insertions(+), 0 deletions(-)
> create mode 100644 arch/arm/include/asm/edid.h
> create mode 100644 drivers/video/edid.c
>
> diff --git a/arch/arm/include/asm/edid.h b/arch/arm/include/asm/edid.h
> new file mode 100644
> index 0000000..843346a
> --- /dev/null
> +++ b/arch/arm/include/asm/edid.h
> @@ -0,0 +1,243 @@
> +/*
> + * edid.h
> + *
> + * Copyright (C) 2011 Texas Instruments
> + * Author: Mythri P K <mythripk@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/>.
> + * History:
> + */
> +
> +#ifndef _EDID_H_
> +#define _EDID_H_
> +
> +/* HDMI EDID Length */
> +#define HDMI_EDID_MAX_LENGTH 512
> +
> +/* HDMI EDID Extension Data Block Tags */
> +#define HDMI_EDID_EX_DATABLOCK_TAG_MASK 0xE0
> +#define HDMI_EDID_EX_DATABLOCK_LEN_MASK 0x1F
> +
> +#define EDID_TIMING_DESCRIPTOR_SIZE 0x12
> +#define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36
> +#define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80
> +#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4
> +#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4
> +
> +/* EDID Detailed Timing Info 0 begin offset */
> +#define HDMI_EDID_DETAILED_TIMING_OFFSET 0x36
> +
> +#define HDMI_EDID_PIX_CLK_OFFSET 0
> +#define HDMI_EDID_H_ACTIVE_OFFSET 2
> +#define HDMI_EDID_H_BLANKING_OFFSET 3
> +#define HDMI_EDID_V_ACTIVE_OFFSET 5
> +#define HDMI_EDID_V_BLANKING_OFFSET 6
> +#define HDMI_EDID_H_SYNC_OFFSET 8
> +#define HDMI_EDID_H_SYNC_PW_OFFSET 9
> +#define HDMI_EDID_V_SYNC_OFFSET 10
> +#define HDMI_EDID_V_SYNC_PW_OFFSET 11
> +#define HDMI_EDID_H_IMAGE_SIZE_OFFSET 12
> +#define HDMI_EDID_V_IMAGE_SIZE_OFFSET 13
> +#define HDMI_EDID_H_BORDER_OFFSET 15
> +#define HDMI_EDID_V_BORDER_OFFSET 16
> +#define HDMI_EDID_FLAGS_OFFSET 17
> +
> +/* HDMI EDID DTDs */
> +#define HDMI_EDID_MAX_DTDS 4
> +
> +/* HDMI EDID DTD Tags */
> +#define HDMI_EDID_DTD_TAG_MONITOR_NAME 0xFC
> +#define HDMI_EDID_DTD_TAG_MONITOR_SERIALNUM 0xFF
> +#define HDMI_EDID_DTD_TAG_MONITOR_LIMITS 0xFD
> +#define HDMI_EDID_DTD_TAG_STANDARD_TIMING_DATA 0xFA
> +#define HDMI_EDID_DTD_TAG_COLOR_POINT_DATA 0xFB
> +#define HDMI_EDID_DTD_TAG_ASCII_STRING 0xFE
> +
> +#define HDMI_IMG_FORMAT_MAX_LENGTH 20
> +#define HDMI_AUDIO_FORMAT_MAX_LENGTH 10
> +
> +/* HDMI EDID Extenion Data Block Values: Video */
> +#define HDMI_EDID_EX_VIDEO_NATIVE 0x80
> +#define HDMI_EDID_EX_VIDEO_MASK 0x7F
> +#define HDMI_EDID_EX_VIDEO_MAX 35
> +
> +#define STANDARD_HDMI_TIMINGS_NB 34
> +#define STANDARD_HDMI_TIMINGS_VESA_START 15
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +enum extension_edid_db {
> + DATABLOCK_AUDIO = 1,
> + DATABLOCK_VIDEO = 2,
> + DATABLOCK_VENDOR = 3,
> + DATABLOCK_SPEAKERS = 4,
> +};
> +
> +struct img_edid {
> + bool pref;
> + int code;
> +};
> +
> +struct image_format {
> + int length;
> + struct img_edid fmt[HDMI_IMG_FORMAT_MAX_LENGTH];
> +};
> +
> +struct audio_edid {
> + int num_of_ch;
> + int format;
> +};
> +
> +struct audio_format {
> + int length;
> + struct audio_edid fmt[HDMI_AUDIO_FORMAT_MAX_LENGTH];
> +};
> +
> +struct latency {
> + /* vid: if indicated, value=1+ms/2 with a max of 251 meaning 500ms */
> + int vid_latency;
> + int aud_latency;
> + int int_vid_latency;
> + int int_aud_latency;
> +};
> +
> +struct deep_color {
> + bool bit_30;
> + bool bit_36;
> + int max_tmds_freq;
> +};
> +
> +/* Video Descriptor Block */
> +struct HDMI_EDID_DTD_VIDEO {
> + u16 pixel_clock; /* 54-55 */
> + u8 horiz_active; /* 56 */
> + u8 horiz_blanking; /* 57 */
> + u8 horiz_high; /* 58 */
> + u8 vert_active; /* 59 */
> + u8 vert_blanking; /* 60 */
> + u8 vert_high; /* 61 */
> + u8 horiz_sync_offset; /* 62 */
> + u8 horiz_sync_pulse; /* 63 */
> + u8 vert_sync_pulse; /* 64 */
> + u8 sync_pulse_high; /* 65 */
> + u8 horiz_image_size; /* 66 */
> + u8 vert_image_size; /* 67 */
> + u8 image_size_high; /* 68 */
> + u8 horiz_border; /* 69 */
> + u8 vert_border; /* 70 */
> + u8 misc_settings; /* 71 */
> +};
> +
> +/* Monitor Limits Descriptor Block */
> +struct HDMI_EDID_DTD_MONITOR {
> + u16 pixel_clock; /* 54-55*/
> + u8 _reserved1; /* 56 */
> + u8 block_type; /* 57 */
> + u8 _reserved2; /* 58 */
> + u8 min_vert_freq; /* 59 */
> + u8 max_vert_freq; /* 60 */
> + u8 min_horiz_freq; /* 61 */
> + u8 max_horiz_freq; /* 62 */
> + u8 pixel_clock_mhz; /* 63 */
> + u8 GTF[2]; /* 64 -65 */
> + u8 start_horiz_freq; /* 66 */
> + u8 C; /* 67 */
> + u8 M[2]; /* 68-69 */
> + u8 K; /* 70 */
> + u8 J; /* 71 */
> +
> +} __packed;
> +
> +/* Text Descriptor Block */
> +struct HDMI_EDID_DTD_TEXT {
> + u16 pixel_clock; /* 54-55 */
> + u8 _reserved1; /* 56 */
> + u8 block_type; /* 57 */
> + u8 _reserved2; /* 58 */
> + u8 text[13]; /* 59-71 */
> +} __packed;
> +
> +/* DTD Union */
> +union HDMI_EDID_DTD {
> + struct HDMI_EDID_DTD_VIDEO video;
> + struct HDMI_EDID_DTD_TEXT monitor_name;
> + struct HDMI_EDID_DTD_TEXT monitor_serial_number;
> + struct HDMI_EDID_DTD_TEXT ascii;
> + struct HDMI_EDID_DTD_MONITOR monitor_limits;
> +} __packed;
> +
> +/* EDID struct */
> +struct HDMI_EDID {
> + u8 header[8]; /* 00-07 */
> + u16 manufacturerID; /* 08-09 */
> + u16 product_id; /* 10-11 */
> + u32 serial_number; /* 12-15 */
> + u8 week_manufactured; /* 16 */
> + u8 year_manufactured; /* 17 */
> + u8 edid_version; /* 18 */
> + u8 edid_revision; /* 19 */
> + u8 video_in_definition; /* 20 */
> + u8 max_horiz_image_size; /* 21 */
> + u8 max_vert_image_size; /* 22 */
> + u8 display_gamma; /* 23 */
> + u8 power_features; /* 24 */
> + u8 chroma_info[10]; /* 25-34 */
> + u8 timing_1; /* 35 */
> + u8 timing_2; /* 36 */
> + u8 timing_3; /* 37 */
> + u8 std_timings[16]; /* 38-53 */
> + union HDMI_EDID_DTD DTD[4]; /* 54-125 */
> + u8 extension_edid; /* 126 */
> + u8 checksum; /* 127 */
> + u8 extension_tag; /* 00 (extensions follow EDID) */
> + u8 extention_rev; /* 01 */
> + u8 offset_dtd; /* 02 */
> + u8 num_dtd; /* 03 */
> + u8 data_block[123]; /* 04 - 126 */
> + u8 extension_checksum; /* 127 */
> +
> + u8 ext_datablock[256];
> +} __packed;
> +
> +struct hdmi_timings {
> +
> + u16 x_res;
> + u16 y_res;
> + u32 pixel_clock; /* pixel clock in KHz */
> + u16 hsw; /* Horizontal synchronization pulse width */
> + u16 hfp; /* Horizontal front porch */
> + u16 hbp; /* Horizontal back porch */
> + u16 vsw; /* Vertical synchronization pulse width */
> + u16 vfp; /* Vertical front porch */
> + u16 vbp; /* Vertical back porch */
> +};
> +
> +int get_edid_timing_info(union HDMI_EDID_DTD *edid_dtd,
> + struct hdmi_timings *timings);
> +void get_eedid_timing_info(int current_descriptor_addrs, u8 *edid ,
> + struct hdmi_timings *timings);
> +int hdmi_get_datablock_offset(u8 *edid, enum extension_edid_db datablock,
> + int *offset);
> +int hdmi_get_image_format(u8 *edid, struct image_format *format);
> +int hdmi_get_audio_format(u8 *edid, struct audio_format *format);
> +void hdmi_get_av_delay(u8 *edid, struct latency *lat);
> +void hdmi_deep_color_support_info(u8 *edid, struct deep_color *format);
> +bool hdmi_tv_yuv_supported(u8 *edid);
> +
> +#ifdef __cplusplus
> +};
> +#endif
> +
> +#endif
> diff --git a/drivers/video/edid.c b/drivers/video/edid.c
> new file mode 100644
> index 0000000..4eb2074
> --- /dev/null
> +++ b/drivers/video/edid.c
> @@ -0,0 +1,340 @@
> +/*
> + * edid.c
> + *
> + * Copyright (C) 2011 Texas Instruments
> + * Author: Mythri P K <mythripk@ti.com>
> + * With EDID parsing for DVI Monitor from Rob Clark <rob@ti.com>
> + *
> + * EDID.c to parse the EDID content.
> + *
> + * 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/>.
> + * History:
> + *
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/err.h>
> +#include <linux/string.h>
> +#include <linux/slab.h>
> +#include <asm/edid.h>
> +
> +/* Standard HDMI/VESA timings */
> +const struct hdmi_timings standard_hdmi_timings[STANDARD_HDMI_TIMINGS_NB] = {
> + {640, 480, 25200, 96, 16, 48, 2, 10, 33},
> + {1280, 720, 74250, 40, 440, 220, 5, 5, 20},
> + {1280, 720, 74250, 40, 110, 220, 5, 5, 20},
> + {720, 480, 27027, 62, 16, 60, 6, 9, 30},
> + {2880, 576, 108000, 256, 48, 272, 5, 5, 39},
> + {1440, 240, 27027, 124, 38, 114, 3, 4, 15},
> + {1440, 288, 27000, 126, 24, 138, 3, 2, 19},
> + {1920, 540, 74250, 44, 528, 148, 5, 2, 15},
> + {1920, 540, 74250, 44, 88, 148, 5, 2, 15},
> + {1920, 1080, 148500, 44, 88, 148, 5, 4, 36},
> + {720, 576, 27000, 64, 12, 68, 5, 5, 39},
> + {1440, 576, 54000, 128, 24, 136, 5, 5, 39},
> + {1920, 1080, 148500, 44, 528, 148, 5, 4, 36},
> + {2880, 480, 108108, 248, 64, 240, 6, 9, 30},
> + {1920, 1080, 74250, 44, 638, 148, 5, 4, 36},
> + /* Vesa frome here */
> + {640, 480, 25175, 96, 16, 48, 2 , 11, 31},
> + {800, 600, 40000, 128, 40, 88, 4 , 1, 23},
> + {848, 480, 33750, 112, 16, 112, 8 , 6, 23},
> + {1280, 768, 79500, 128, 64, 192, 7 , 3, 20},
> + {1280, 800, 83500, 128, 72, 200, 6 , 3, 22},
> + {1360, 768, 85500, 112, 64, 256, 6 , 3, 18},
> + {1280, 960, 108000, 112, 96, 312, 3 , 1, 36},
> + {1280, 1024, 108000, 112, 48, 248, 3 , 1, 38},
> + {1024, 768, 65000, 136, 24, 160, 6, 3, 29},
> + {1400, 1050, 121750, 144, 88, 232, 4, 3, 32},
> + {1440, 900, 106500, 152, 80, 232, 6, 3, 25},
> + {1680, 1050, 146250, 176 , 104, 280, 6, 3, 30},
> + {1366, 768, 85500, 143, 70, 213, 3, 3, 24},
> + {1920, 1080, 148500, 44, 88, 80, 5, 4, 36},
> + {1280, 768, 68250, 32, 48, 80, 7, 3, 12},
> + {1400, 1050, 101000, 32, 48, 80, 4, 3, 23},
> + {1680, 1050, 119000, 32, 48, 80, 6, 3, 21},
> + {1280, 800, 79500, 32, 48, 80, 6, 3, 14},
> + {1280, 720, 74250, 40, 110, 220, 5, 5, 20}
> +};
> +
> +int get_edid_timing_info(union HDMI_EDID_DTD *edid_dtd,
> + struct hdmi_timings *timings)
> +{
> + if (edid_dtd->video.pixel_clock) {
> + struct HDMI_EDID_DTD_VIDEO *vid = &edid_dtd->video;
> +
> + timings->pixel_clock = 10 * vid->pixel_clock;
> + timings->x_res = vid->horiz_active |
> + (((u16)vid->horiz_high & 0xf0) << 4);
> + timings->y_res = vid->vert_active |
> + (((u16)vid->vert_high & 0xf0) << 4);
> + timings->hfp = vid->horiz_sync_offset |
> + (((u16)vid->sync_pulse_high & 0xc0) << 2);
> + timings->hsw = vid->horiz_sync_pulse |
> + (((u16)vid->sync_pulse_high & 0x30) << 4);
> + timings->hbp = (vid->horiz_blanking |
> + (((u16)vid->horiz_high & 0x0f) << 8)) -
> + (timings->hfp + timings->hsw);
> + timings->vfp = ((vid->vert_sync_pulse & 0xf0) >> 4) |
> + ((vid->sync_pulse_high & 0x0f) << 2);
> + timings->vsw = (vid->vert_sync_pulse & 0x0f) |
> + ((vid->sync_pulse_high & 0x03) << 4);
> + timings->vbp = (vid->vert_blanking |
> + (((u16)vid->vert_high & 0x0f) << 8)) -
> + (timings->vfp + timings->vsw);
> + return 0;
> + }
> +
> + switch (edid_dtd->monitor_name.block_type) {
> + case HDMI_EDID_DTD_TAG_STANDARD_TIMING_DATA:
> + printk(KERN_INFO "standard timing data\n");
> + return -EINVAL;
> + case HDMI_EDID_DTD_TAG_COLOR_POINT_DATA:
> + printk(KERN_INFO "color point data\n");
> + return -EINVAL;
> + case HDMI_EDID_DTD_TAG_MONITOR_NAME:
> + printk(KERN_INFO "monitor name: %s\n",
> + edid_dtd->monitor_name.text);
> + return -EINVAL;
> + case HDMI_EDID_DTD_TAG_MONITOR_LIMITS:
> + {
> + int i, max_area = 0, best_idx = -1;
> + struct HDMI_EDID_DTD_MONITOR *limits > + &edid_dtd->monitor_limits;
> +
> + printk(KERN_DEBUG " monitor limits\n");
> + printk(KERN_DEBUG " min_vert_freq=%d\n",
> + limits->min_vert_freq);
> + printk(KERN_DEBUG " max_vert_freq=%d\n",
> + limits->max_vert_freq);
> + printk(KERN_DEBUG " min_horiz_freq=%d\n",
> + limits->min_horiz_freq);
> + printk(KERN_DEBUG " max_horiz_freq=%d\n",
> + limits->max_horiz_freq);
> + printk(KERN_DEBUG " pixel_clock_mhz=%d\n",
> + limits->pixel_clock_mhz * 10);
> +
> + /* find the highest matching resolution (w*h) */
> +
> + /*
> + * XXX since this is mainly for DVI monitors, should we only
> + * support VESA timings? My monitor at home would pick
> + * 1920x1080 otherwise, but that seems to not work well (monitor
> + * blanks out and comes back, and picture doesn't fill full
> + * screen, but leaves a black bar on left (native res is
> + * 2048x1152). However if I only consider VESA timings, it picks
> + * 1680x1050 and the picture is stable and fills whole screen
> + */
> + for (i = STANDARD_HDMI_TIMINGS_VESA_START;
> + i < STANDARD_HDMI_TIMINGS_NB; i++) {
> + const struct hdmi_timings *timings > + &standard_hdmi_timings[i];
> + int hz, hscan, pixclock;
> + int vtotal, htotal;
> + htotal = timings->hbp + timings->hfp +
> + timings->hsw + timings->x_res;
> + vtotal = timings->vbp + timings->vfp +
> + timings->vsw + timings->y_res;
> +
> + /* NOTE: We don't support interlaced mode for VESA */
> + pixclock = timings->pixel_clock * 1000;
> + hscan = (pixclock + htotal / 2) / htotal;
> + hscan = (hscan + 500) / 1000 * 1000;
> + hz = (hscan + vtotal / 2) / vtotal;
> + hscan /= 1000;
> + pixclock /= 1000000;
> + if ((pixclock < (limits->pixel_clock_mhz * 10)) &&
> + (limits->min_horiz_freq <= hscan) &&
> + (hscan <= limits->max_horiz_freq) &&
> + (limits->min_vert_freq <= hz) &&
> + (hz <= limits->max_vert_freq)) {
> + int area = timings->x_res * timings->y_res;
> + printk(KERN_INFO " -> %d: %dx%d\n", i,
> + timings->x_res, timings->y_res);
> + if (area > max_area) {
> + max_area = area;
> + best_idx = i;
> + }
> + }
> + }
> + if (best_idx > 0) {
> + *timings = standard_hdmi_timings[best_idx];
> + printk(KERN_DEBUG "found best resolution: %dx%d (%d)\n",
> + timings->x_res, timings->y_res, best_idx);
> + }
> + return 0;
> + }
> + case HDMI_EDID_DTD_TAG_ASCII_STRING:
> + printk(KERN_INFO "ascii string: %s\n", edid_dtd->ascii.text);
> + return -EINVAL;
> + case HDMI_EDID_DTD_TAG_MONITOR_SERIALNUM:
> + printk(KERN_INFO "monitor serialnum: %s\n",
> + edid_dtd->monitor_serial_number.text);
> + return -EINVAL;
> + default:
> + printk(KERN_INFO "unsupported EDID descriptor block format\n");
> + return -EINVAL;
> + }
> +}
> +
> +void get_eedid_timing_info(int current_descriptor_addrs, u8 *edid ,
> + struct hdmi_timings *timings)
> +{
> + timings->x_res = (((edid[current_descriptor_addrs + 4] & 0xF0) << 4)
> + | edid[current_descriptor_addrs + 2]);
> + timings->y_res = (((edid[current_descriptor_addrs + 7] & 0xF0) << 4)
> + | edid[current_descriptor_addrs + 5]);
> + timings->pixel_clock = ((edid[current_descriptor_addrs + 1] << 8)
> + | edid[current_descriptor_addrs]);
> + timings->pixel_clock = 10 * timings->pixel_clock;
> + timings->hfp = edid[current_descriptor_addrs + 8];
> + timings->hsw = edid[current_descriptor_addrs + 9];
> + timings->hbp = (((edid[current_descriptor_addrs + 4] & 0x0F) << 8)
> + | edid[current_descriptor_addrs + 3]) -
> + (timings->hfp + timings->hsw);
> + timings->vfp = ((edid[current_descriptor_addrs + 10] & 0xF0) >> 4);
> + timings->vsw = (edid[current_descriptor_addrs + 10] & 0x0F);
> + timings->vbp = (((edid[current_descriptor_addrs + 7] & 0x0F) << 8)
> + | edid[current_descriptor_addrs + 6]) -
> + (timings->vfp + timings->vsw);
> +}
> +
> +int hdmi_get_datablock_offset(u8 *edid, enum extension_edid_db datablock,
> + int *offset)
> +{
> + int current_byte, disp, i = 0, length = 0;
> +
> + if (edid[0x7e] = 0x00)
> + return -EINVAL;
> +
> + disp = edid[(0x80) + 2];
> + if (disp = 0x4)
> + return -EINVAL;
> +
> + i = 0x80 + 0x4;
> + printk(KERN_INFO "%x\n", i);
> + while (i < (0x80 + disp)) {
> + current_byte = edid[i];
> + if ((current_byte >> 5) = datablock) {
> + *offset = i;
> + printk(KERN_INFO "datablock %d %d\n",
> + datablock, *offset);
> + return 0;
> + } else {
> + length = (current_byte &
> + HDMI_EDID_EX_DATABLOCK_LEN_MASK) + 1;
> + i += length;
> + }
> + }
> + return -EINVAL;
> +}
> +
> +int hdmi_get_image_format(u8 *edid, struct image_format *format)
> +{
> + int offset, current_byte, j = 0, length = 0;
> + enum extension_edid_db vsdb = DATABLOCK_VIDEO;
> + format->length = 0;
> +
> + memset(format->fmt, 0, sizeof(format->fmt));
> + if (!hdmi_get_datablock_offset(edid, vsdb, &offset)) {
> + current_byte = edid[offset];
> + length = current_byte & HDMI_EDID_EX_DATABLOCK_LEN_MASK;
> +
> + if (length >= HDMI_IMG_FORMAT_MAX_LENGTH)
> + format->length = HDMI_IMG_FORMAT_MAX_LENGTH;
> + else
> + format->length = length;
> +
> + for (j = 1 ; j < length ; j++) {
> + current_byte = edid[offset+j];
> + format->fmt[j-1].code = current_byte & 0x7F;
> + format->fmt[j-1].pref = current_byte & 0x80;
> + }
> + }
> + return 0;
> +}
> +
> +int hdmi_get_audio_format(u8 *edid, struct audio_format *format)
> +{
> + int offset, current_byte, j = 0, length = 0;
> + enum extension_edid_db vsdb = DATABLOCK_AUDIO;
> +
> + format->length = 0;
> + memset(format->fmt, 0, sizeof(format->fmt));
> +
> + if (!hdmi_get_datablock_offset(edid, vsdb, &offset)) {
> + current_byte = edid[offset];
> + length = current_byte & HDMI_EDID_EX_DATABLOCK_LEN_MASK;
> +
> + if (length >= HDMI_AUDIO_FORMAT_MAX_LENGTH)
> + format->length = HDMI_AUDIO_FORMAT_MAX_LENGTH;
> + else
> + format->length = length;
> +
> + for (j = 1 ; j < length ; j++) {
> + if (j%3 = 1) {
> + current_byte = edid[offset + j];
> + format->fmt[j-1].format = current_byte & 0x78;
> + format->fmt[j-1].num_of_ch > + (current_byte & 0x07) + 1;
> + }
> + }
> + }
> + return 0;
> +}
> +
> +void hdmi_get_av_delay(u8 *edid, struct latency *lat)
> +{
> + int offset, current_byte, length = 0;
> + enum extension_edid_db vsdb = DATABLOCK_VENDOR;
> +
> + if (!hdmi_get_datablock_offset(edid, vsdb, &offset)) {
> + current_byte = edid[offset];
> + length = current_byte & HDMI_EDID_EX_DATABLOCK_LEN_MASK;
> + if (length >= 8 && ((current_byte + 8) & 0x80)) {
> + lat->vid_latency = (edid[offset + 8] - 1) * 2;
> + lat->aud_latency = (edid[offset + 9] - 1) * 2;
> + }
> + if (length >= 8 && ((current_byte + 8) & 0xC0)) {
> + lat->int_vid_latency = (edid[offset + 10] - 1) * 2;
> + lat->int_aud_latency = (edid[offset + 11] - 1) * 2;
> + }
> + }
> +}
> +
> +void hdmi_deep_color_support_info(u8 *edid, struct deep_color *format)
> +{
> + int offset, current_byte, length = 0;
> + enum extension_edid_db vsdb = DATABLOCK_VENDOR;
> + memset(format, 0, sizeof(*format));
> +
> + if (!hdmi_get_datablock_offset(edid, vsdb, &offset)) {
> + current_byte = edid[offset];
> + length = current_byte & HDMI_EDID_EX_DATABLOCK_LEN_MASK;
> + if (length >= 6) {
> + format->bit_30 = (edid[offset + 6] & 0x10);
> + format->bit_36 = (edid[offset + 6] & 0x20);
> + }
> + if (length >= 7)
> + format->max_tmds_freq = (edid[offset + 7]) * 5;
> + }
> +}
> +
> +bool hdmi_tv_yuv_supported(u8 *edid)
> +{
> + if (edid[0x7e] != 0x00 && edid[0x83] & 0x30) {
> + printk(KERN_INFO "YUV supported");
> + return true;
> + }
> + return false;
> +}
^ permalink raw reply
* [RFC PATCH] HDMI:Support for EDID parsing in kernel.
From: Mythri P K @ 2011-03-22 17:44 UTC (permalink / raw)
To: linux-fbdev, linux-omap, linux-media; +Cc: Mythri P K
Adding support for common EDID parsing in kernel.
EDID - Extended display identification data is a data structure provided by
a digital display to describe its capabilities to a video source, This a
standard supported by CEA and VESA.
There are several custom implementations for parsing EDID in kernel, some
of them are present in fbmon.c, drm_edid.c, sh_mobile_hdmi.c, Ideally
parsing of EDID should be done in a library, which is agnostic of the
framework (V4l2, DRM, FB) which is using the functionality, just based on
the raw EDID pointer with size/segment information.
With other RFC's such as the one below, which tries to standardize HDMI API's
It would be better to have a common EDID code in one place.It also helps to
provide better interoperability with variety of TV/Monitor may be even by
listing out quirks which might get missed with several custom implementation
of EDID.
http://permalink.gmane.org/gmane.linux.drivers.video-input-infrastructure/30401
This patch tries to add functions to parse some portion EDID (detailed timing,
monitor limits, AV delay information, deep color mode support, Audio and VSDB)
If we can align on this library approach i can enhance this library to parse
other blocks and probably we could also add quirks from other implementation
as well.
Signed-off-by: Mythri P K <mythripk@ti.com>
---
arch/arm/include/asm/edid.h | 243 ++++++++++++++++++++++++++++++
drivers/video/edid.c | 340 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 583 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/include/asm/edid.h
create mode 100644 drivers/video/edid.c
diff --git a/arch/arm/include/asm/edid.h b/arch/arm/include/asm/edid.h
new file mode 100644
index 0000000..843346a
--- /dev/null
+++ b/arch/arm/include/asm/edid.h
@@ -0,0 +1,243 @@
+/*
+ * edid.h
+ *
+ * Copyright (C) 2011 Texas Instruments
+ * Author: Mythri P K <mythripk@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/>.
+ * History:
+ */
+
+#ifndef _EDID_H_
+#define _EDID_H_
+
+/* HDMI EDID Length */
+#define HDMI_EDID_MAX_LENGTH 512
+
+/* HDMI EDID Extension Data Block Tags */
+#define HDMI_EDID_EX_DATABLOCK_TAG_MASK 0xE0
+#define HDMI_EDID_EX_DATABLOCK_LEN_MASK 0x1F
+
+#define EDID_TIMING_DESCRIPTOR_SIZE 0x12
+#define EDID_DESCRIPTOR_BLOCK0_ADDRESS 0x36
+#define EDID_DESCRIPTOR_BLOCK1_ADDRESS 0x80
+#define EDID_SIZE_BLOCK0_TIMING_DESCRIPTOR 4
+#define EDID_SIZE_BLOCK1_TIMING_DESCRIPTOR 4
+
+/* EDID Detailed Timing Info 0 begin offset */
+#define HDMI_EDID_DETAILED_TIMING_OFFSET 0x36
+
+#define HDMI_EDID_PIX_CLK_OFFSET 0
+#define HDMI_EDID_H_ACTIVE_OFFSET 2
+#define HDMI_EDID_H_BLANKING_OFFSET 3
+#define HDMI_EDID_V_ACTIVE_OFFSET 5
+#define HDMI_EDID_V_BLANKING_OFFSET 6
+#define HDMI_EDID_H_SYNC_OFFSET 8
+#define HDMI_EDID_H_SYNC_PW_OFFSET 9
+#define HDMI_EDID_V_SYNC_OFFSET 10
+#define HDMI_EDID_V_SYNC_PW_OFFSET 11
+#define HDMI_EDID_H_IMAGE_SIZE_OFFSET 12
+#define HDMI_EDID_V_IMAGE_SIZE_OFFSET 13
+#define HDMI_EDID_H_BORDER_OFFSET 15
+#define HDMI_EDID_V_BORDER_OFFSET 16
+#define HDMI_EDID_FLAGS_OFFSET 17
+
+/* HDMI EDID DTDs */
+#define HDMI_EDID_MAX_DTDS 4
+
+/* HDMI EDID DTD Tags */
+#define HDMI_EDID_DTD_TAG_MONITOR_NAME 0xFC
+#define HDMI_EDID_DTD_TAG_MONITOR_SERIALNUM 0xFF
+#define HDMI_EDID_DTD_TAG_MONITOR_LIMITS 0xFD
+#define HDMI_EDID_DTD_TAG_STANDARD_TIMING_DATA 0xFA
+#define HDMI_EDID_DTD_TAG_COLOR_POINT_DATA 0xFB
+#define HDMI_EDID_DTD_TAG_ASCII_STRING 0xFE
+
+#define HDMI_IMG_FORMAT_MAX_LENGTH 20
+#define HDMI_AUDIO_FORMAT_MAX_LENGTH 10
+
+/* HDMI EDID Extenion Data Block Values: Video */
+#define HDMI_EDID_EX_VIDEO_NATIVE 0x80
+#define HDMI_EDID_EX_VIDEO_MASK 0x7F
+#define HDMI_EDID_EX_VIDEO_MAX 35
+
+#define STANDARD_HDMI_TIMINGS_NB 34
+#define STANDARD_HDMI_TIMINGS_VESA_START 15
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum extension_edid_db {
+ DATABLOCK_AUDIO = 1,
+ DATABLOCK_VIDEO = 2,
+ DATABLOCK_VENDOR = 3,
+ DATABLOCK_SPEAKERS = 4,
+};
+
+struct img_edid {
+ bool pref;
+ int code;
+};
+
+struct image_format {
+ int length;
+ struct img_edid fmt[HDMI_IMG_FORMAT_MAX_LENGTH];
+};
+
+struct audio_edid {
+ int num_of_ch;
+ int format;
+};
+
+struct audio_format {
+ int length;
+ struct audio_edid fmt[HDMI_AUDIO_FORMAT_MAX_LENGTH];
+};
+
+struct latency {
+ /* vid: if indicated, value=1+ms/2 with a max of 251 meaning 500ms */
+ int vid_latency;
+ int aud_latency;
+ int int_vid_latency;
+ int int_aud_latency;
+};
+
+struct deep_color {
+ bool bit_30;
+ bool bit_36;
+ int max_tmds_freq;
+};
+
+/* Video Descriptor Block */
+struct HDMI_EDID_DTD_VIDEO {
+ u16 pixel_clock; /* 54-55 */
+ u8 horiz_active; /* 56 */
+ u8 horiz_blanking; /* 57 */
+ u8 horiz_high; /* 58 */
+ u8 vert_active; /* 59 */
+ u8 vert_blanking; /* 60 */
+ u8 vert_high; /* 61 */
+ u8 horiz_sync_offset; /* 62 */
+ u8 horiz_sync_pulse; /* 63 */
+ u8 vert_sync_pulse; /* 64 */
+ u8 sync_pulse_high; /* 65 */
+ u8 horiz_image_size; /* 66 */
+ u8 vert_image_size; /* 67 */
+ u8 image_size_high; /* 68 */
+ u8 horiz_border; /* 69 */
+ u8 vert_border; /* 70 */
+ u8 misc_settings; /* 71 */
+};
+
+/* Monitor Limits Descriptor Block */
+struct HDMI_EDID_DTD_MONITOR {
+ u16 pixel_clock; /* 54-55*/
+ u8 _reserved1; /* 56 */
+ u8 block_type; /* 57 */
+ u8 _reserved2; /* 58 */
+ u8 min_vert_freq; /* 59 */
+ u8 max_vert_freq; /* 60 */
+ u8 min_horiz_freq; /* 61 */
+ u8 max_horiz_freq; /* 62 */
+ u8 pixel_clock_mhz; /* 63 */
+ u8 GTF[2]; /* 64 -65 */
+ u8 start_horiz_freq; /* 66 */
+ u8 C; /* 67 */
+ u8 M[2]; /* 68-69 */
+ u8 K; /* 70 */
+ u8 J; /* 71 */
+
+} __packed;
+
+/* Text Descriptor Block */
+struct HDMI_EDID_DTD_TEXT {
+ u16 pixel_clock; /* 54-55 */
+ u8 _reserved1; /* 56 */
+ u8 block_type; /* 57 */
+ u8 _reserved2; /* 58 */
+ u8 text[13]; /* 59-71 */
+} __packed;
+
+/* DTD Union */
+union HDMI_EDID_DTD {
+ struct HDMI_EDID_DTD_VIDEO video;
+ struct HDMI_EDID_DTD_TEXT monitor_name;
+ struct HDMI_EDID_DTD_TEXT monitor_serial_number;
+ struct HDMI_EDID_DTD_TEXT ascii;
+ struct HDMI_EDID_DTD_MONITOR monitor_limits;
+} __packed;
+
+/* EDID struct */
+struct HDMI_EDID {
+ u8 header[8]; /* 00-07 */
+ u16 manufacturerID; /* 08-09 */
+ u16 product_id; /* 10-11 */
+ u32 serial_number; /* 12-15 */
+ u8 week_manufactured; /* 16 */
+ u8 year_manufactured; /* 17 */
+ u8 edid_version; /* 18 */
+ u8 edid_revision; /* 19 */
+ u8 video_in_definition; /* 20 */
+ u8 max_horiz_image_size; /* 21 */
+ u8 max_vert_image_size; /* 22 */
+ u8 display_gamma; /* 23 */
+ u8 power_features; /* 24 */
+ u8 chroma_info[10]; /* 25-34 */
+ u8 timing_1; /* 35 */
+ u8 timing_2; /* 36 */
+ u8 timing_3; /* 37 */
+ u8 std_timings[16]; /* 38-53 */
+ union HDMI_EDID_DTD DTD[4]; /* 54-125 */
+ u8 extension_edid; /* 126 */
+ u8 checksum; /* 127 */
+ u8 extension_tag; /* 00 (extensions follow EDID) */
+ u8 extention_rev; /* 01 */
+ u8 offset_dtd; /* 02 */
+ u8 num_dtd; /* 03 */
+ u8 data_block[123]; /* 04 - 126 */
+ u8 extension_checksum; /* 127 */
+
+ u8 ext_datablock[256];
+} __packed;
+
+struct hdmi_timings {
+
+ u16 x_res;
+ u16 y_res;
+ u32 pixel_clock; /* pixel clock in KHz */
+ u16 hsw; /* Horizontal synchronization pulse width */
+ u16 hfp; /* Horizontal front porch */
+ u16 hbp; /* Horizontal back porch */
+ u16 vsw; /* Vertical synchronization pulse width */
+ u16 vfp; /* Vertical front porch */
+ u16 vbp; /* Vertical back porch */
+};
+
+int get_edid_timing_info(union HDMI_EDID_DTD *edid_dtd,
+ struct hdmi_timings *timings);
+void get_eedid_timing_info(int current_descriptor_addrs, u8 *edid ,
+ struct hdmi_timings *timings);
+int hdmi_get_datablock_offset(u8 *edid, enum extension_edid_db datablock,
+ int *offset);
+int hdmi_get_image_format(u8 *edid, struct image_format *format);
+int hdmi_get_audio_format(u8 *edid, struct audio_format *format);
+void hdmi_get_av_delay(u8 *edid, struct latency *lat);
+void hdmi_deep_color_support_info(u8 *edid, struct deep_color *format);
+bool hdmi_tv_yuv_supported(u8 *edid);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
diff --git a/drivers/video/edid.c b/drivers/video/edid.c
new file mode 100644
index 0000000..4eb2074
--- /dev/null
+++ b/drivers/video/edid.c
@@ -0,0 +1,340 @@
+/*
+ * edid.c
+ *
+ * Copyright (C) 2011 Texas Instruments
+ * Author: Mythri P K <mythripk@ti.com>
+ * With EDID parsing for DVI Monitor from Rob Clark <rob@ti.com>
+ *
+ * EDID.c to parse the EDID content.
+ *
+ * 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/>.
+ * History:
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <asm/edid.h>
+
+/* Standard HDMI/VESA timings */
+const struct hdmi_timings standard_hdmi_timings[STANDARD_HDMI_TIMINGS_NB] = {
+ {640, 480, 25200, 96, 16, 48, 2, 10, 33},
+ {1280, 720, 74250, 40, 440, 220, 5, 5, 20},
+ {1280, 720, 74250, 40, 110, 220, 5, 5, 20},
+ {720, 480, 27027, 62, 16, 60, 6, 9, 30},
+ {2880, 576, 108000, 256, 48, 272, 5, 5, 39},
+ {1440, 240, 27027, 124, 38, 114, 3, 4, 15},
+ {1440, 288, 27000, 126, 24, 138, 3, 2, 19},
+ {1920, 540, 74250, 44, 528, 148, 5, 2, 15},
+ {1920, 540, 74250, 44, 88, 148, 5, 2, 15},
+ {1920, 1080, 148500, 44, 88, 148, 5, 4, 36},
+ {720, 576, 27000, 64, 12, 68, 5, 5, 39},
+ {1440, 576, 54000, 128, 24, 136, 5, 5, 39},
+ {1920, 1080, 148500, 44, 528, 148, 5, 4, 36},
+ {2880, 480, 108108, 248, 64, 240, 6, 9, 30},
+ {1920, 1080, 74250, 44, 638, 148, 5, 4, 36},
+ /* Vesa frome here */
+ {640, 480, 25175, 96, 16, 48, 2 , 11, 31},
+ {800, 600, 40000, 128, 40, 88, 4 , 1, 23},
+ {848, 480, 33750, 112, 16, 112, 8 , 6, 23},
+ {1280, 768, 79500, 128, 64, 192, 7 , 3, 20},
+ {1280, 800, 83500, 128, 72, 200, 6 , 3, 22},
+ {1360, 768, 85500, 112, 64, 256, 6 , 3, 18},
+ {1280, 960, 108000, 112, 96, 312, 3 , 1, 36},
+ {1280, 1024, 108000, 112, 48, 248, 3 , 1, 38},
+ {1024, 768, 65000, 136, 24, 160, 6, 3, 29},
+ {1400, 1050, 121750, 144, 88, 232, 4, 3, 32},
+ {1440, 900, 106500, 152, 80, 232, 6, 3, 25},
+ {1680, 1050, 146250, 176 , 104, 280, 6, 3, 30},
+ {1366, 768, 85500, 143, 70, 213, 3, 3, 24},
+ {1920, 1080, 148500, 44, 88, 80, 5, 4, 36},
+ {1280, 768, 68250, 32, 48, 80, 7, 3, 12},
+ {1400, 1050, 101000, 32, 48, 80, 4, 3, 23},
+ {1680, 1050, 119000, 32, 48, 80, 6, 3, 21},
+ {1280, 800, 79500, 32, 48, 80, 6, 3, 14},
+ {1280, 720, 74250, 40, 110, 220, 5, 5, 20}
+};
+
+int get_edid_timing_info(union HDMI_EDID_DTD *edid_dtd,
+ struct hdmi_timings *timings)
+{
+ if (edid_dtd->video.pixel_clock) {
+ struct HDMI_EDID_DTD_VIDEO *vid = &edid_dtd->video;
+
+ timings->pixel_clock = 10 * vid->pixel_clock;
+ timings->x_res = vid->horiz_active |
+ (((u16)vid->horiz_high & 0xf0) << 4);
+ timings->y_res = vid->vert_active |
+ (((u16)vid->vert_high & 0xf0) << 4);
+ timings->hfp = vid->horiz_sync_offset |
+ (((u16)vid->sync_pulse_high & 0xc0) << 2);
+ timings->hsw = vid->horiz_sync_pulse |
+ (((u16)vid->sync_pulse_high & 0x30) << 4);
+ timings->hbp = (vid->horiz_blanking |
+ (((u16)vid->horiz_high & 0x0f) << 8)) -
+ (timings->hfp + timings->hsw);
+ timings->vfp = ((vid->vert_sync_pulse & 0xf0) >> 4) |
+ ((vid->sync_pulse_high & 0x0f) << 2);
+ timings->vsw = (vid->vert_sync_pulse & 0x0f) |
+ ((vid->sync_pulse_high & 0x03) << 4);
+ timings->vbp = (vid->vert_blanking |
+ (((u16)vid->vert_high & 0x0f) << 8)) -
+ (timings->vfp + timings->vsw);
+ return 0;
+ }
+
+ switch (edid_dtd->monitor_name.block_type) {
+ case HDMI_EDID_DTD_TAG_STANDARD_TIMING_DATA:
+ printk(KERN_INFO "standard timing data\n");
+ return -EINVAL;
+ case HDMI_EDID_DTD_TAG_COLOR_POINT_DATA:
+ printk(KERN_INFO "color point data\n");
+ return -EINVAL;
+ case HDMI_EDID_DTD_TAG_MONITOR_NAME:
+ printk(KERN_INFO "monitor name: %s\n",
+ edid_dtd->monitor_name.text);
+ return -EINVAL;
+ case HDMI_EDID_DTD_TAG_MONITOR_LIMITS:
+ {
+ int i, max_area = 0, best_idx = -1;
+ struct HDMI_EDID_DTD_MONITOR *limits + &edid_dtd->monitor_limits;
+
+ printk(KERN_DEBUG " monitor limits\n");
+ printk(KERN_DEBUG " min_vert_freq=%d\n",
+ limits->min_vert_freq);
+ printk(KERN_DEBUG " max_vert_freq=%d\n",
+ limits->max_vert_freq);
+ printk(KERN_DEBUG " min_horiz_freq=%d\n",
+ limits->min_horiz_freq);
+ printk(KERN_DEBUG " max_horiz_freq=%d\n",
+ limits->max_horiz_freq);
+ printk(KERN_DEBUG " pixel_clock_mhz=%d\n",
+ limits->pixel_clock_mhz * 10);
+
+ /* find the highest matching resolution (w*h) */
+
+ /*
+ * XXX since this is mainly for DVI monitors, should we only
+ * support VESA timings? My monitor at home would pick
+ * 1920x1080 otherwise, but that seems to not work well (monitor
+ * blanks out and comes back, and picture doesn't fill full
+ * screen, but leaves a black bar on left (native res is
+ * 2048x1152). However if I only consider VESA timings, it picks
+ * 1680x1050 and the picture is stable and fills whole screen
+ */
+ for (i = STANDARD_HDMI_TIMINGS_VESA_START;
+ i < STANDARD_HDMI_TIMINGS_NB; i++) {
+ const struct hdmi_timings *timings + &standard_hdmi_timings[i];
+ int hz, hscan, pixclock;
+ int vtotal, htotal;
+ htotal = timings->hbp + timings->hfp +
+ timings->hsw + timings->x_res;
+ vtotal = timings->vbp + timings->vfp +
+ timings->vsw + timings->y_res;
+
+ /* NOTE: We don't support interlaced mode for VESA */
+ pixclock = timings->pixel_clock * 1000;
+ hscan = (pixclock + htotal / 2) / htotal;
+ hscan = (hscan + 500) / 1000 * 1000;
+ hz = (hscan + vtotal / 2) / vtotal;
+ hscan /= 1000;
+ pixclock /= 1000000;
+ if ((pixclock < (limits->pixel_clock_mhz * 10)) &&
+ (limits->min_horiz_freq <= hscan) &&
+ (hscan <= limits->max_horiz_freq) &&
+ (limits->min_vert_freq <= hz) &&
+ (hz <= limits->max_vert_freq)) {
+ int area = timings->x_res * timings->y_res;
+ printk(KERN_INFO " -> %d: %dx%d\n", i,
+ timings->x_res, timings->y_res);
+ if (area > max_area) {
+ max_area = area;
+ best_idx = i;
+ }
+ }
+ }
+ if (best_idx > 0) {
+ *timings = standard_hdmi_timings[best_idx];
+ printk(KERN_DEBUG "found best resolution: %dx%d (%d)\n",
+ timings->x_res, timings->y_res, best_idx);
+ }
+ return 0;
+ }
+ case HDMI_EDID_DTD_TAG_ASCII_STRING:
+ printk(KERN_INFO "ascii string: %s\n", edid_dtd->ascii.text);
+ return -EINVAL;
+ case HDMI_EDID_DTD_TAG_MONITOR_SERIALNUM:
+ printk(KERN_INFO "monitor serialnum: %s\n",
+ edid_dtd->monitor_serial_number.text);
+ return -EINVAL;
+ default:
+ printk(KERN_INFO "unsupported EDID descriptor block format\n");
+ return -EINVAL;
+ }
+}
+
+void get_eedid_timing_info(int current_descriptor_addrs, u8 *edid ,
+ struct hdmi_timings *timings)
+{
+ timings->x_res = (((edid[current_descriptor_addrs + 4] & 0xF0) << 4)
+ | edid[current_descriptor_addrs + 2]);
+ timings->y_res = (((edid[current_descriptor_addrs + 7] & 0xF0) << 4)
+ | edid[current_descriptor_addrs + 5]);
+ timings->pixel_clock = ((edid[current_descriptor_addrs + 1] << 8)
+ | edid[current_descriptor_addrs]);
+ timings->pixel_clock = 10 * timings->pixel_clock;
+ timings->hfp = edid[current_descriptor_addrs + 8];
+ timings->hsw = edid[current_descriptor_addrs + 9];
+ timings->hbp = (((edid[current_descriptor_addrs + 4] & 0x0F) << 8)
+ | edid[current_descriptor_addrs + 3]) -
+ (timings->hfp + timings->hsw);
+ timings->vfp = ((edid[current_descriptor_addrs + 10] & 0xF0) >> 4);
+ timings->vsw = (edid[current_descriptor_addrs + 10] & 0x0F);
+ timings->vbp = (((edid[current_descriptor_addrs + 7] & 0x0F) << 8)
+ | edid[current_descriptor_addrs + 6]) -
+ (timings->vfp + timings->vsw);
+}
+
+int hdmi_get_datablock_offset(u8 *edid, enum extension_edid_db datablock,
+ int *offset)
+{
+ int current_byte, disp, i = 0, length = 0;
+
+ if (edid[0x7e] = 0x00)
+ return -EINVAL;
+
+ disp = edid[(0x80) + 2];
+ if (disp = 0x4)
+ return -EINVAL;
+
+ i = 0x80 + 0x4;
+ printk(KERN_INFO "%x\n", i);
+ while (i < (0x80 + disp)) {
+ current_byte = edid[i];
+ if ((current_byte >> 5) = datablock) {
+ *offset = i;
+ printk(KERN_INFO "datablock %d %d\n",
+ datablock, *offset);
+ return 0;
+ } else {
+ length = (current_byte &
+ HDMI_EDID_EX_DATABLOCK_LEN_MASK) + 1;
+ i += length;
+ }
+ }
+ return -EINVAL;
+}
+
+int hdmi_get_image_format(u8 *edid, struct image_format *format)
+{
+ int offset, current_byte, j = 0, length = 0;
+ enum extension_edid_db vsdb = DATABLOCK_VIDEO;
+ format->length = 0;
+
+ memset(format->fmt, 0, sizeof(format->fmt));
+ if (!hdmi_get_datablock_offset(edid, vsdb, &offset)) {
+ current_byte = edid[offset];
+ length = current_byte & HDMI_EDID_EX_DATABLOCK_LEN_MASK;
+
+ if (length >= HDMI_IMG_FORMAT_MAX_LENGTH)
+ format->length = HDMI_IMG_FORMAT_MAX_LENGTH;
+ else
+ format->length = length;
+
+ for (j = 1 ; j < length ; j++) {
+ current_byte = edid[offset+j];
+ format->fmt[j-1].code = current_byte & 0x7F;
+ format->fmt[j-1].pref = current_byte & 0x80;
+ }
+ }
+ return 0;
+}
+
+int hdmi_get_audio_format(u8 *edid, struct audio_format *format)
+{
+ int offset, current_byte, j = 0, length = 0;
+ enum extension_edid_db vsdb = DATABLOCK_AUDIO;
+
+ format->length = 0;
+ memset(format->fmt, 0, sizeof(format->fmt));
+
+ if (!hdmi_get_datablock_offset(edid, vsdb, &offset)) {
+ current_byte = edid[offset];
+ length = current_byte & HDMI_EDID_EX_DATABLOCK_LEN_MASK;
+
+ if (length >= HDMI_AUDIO_FORMAT_MAX_LENGTH)
+ format->length = HDMI_AUDIO_FORMAT_MAX_LENGTH;
+ else
+ format->length = length;
+
+ for (j = 1 ; j < length ; j++) {
+ if (j%3 = 1) {
+ current_byte = edid[offset + j];
+ format->fmt[j-1].format = current_byte & 0x78;
+ format->fmt[j-1].num_of_ch + (current_byte & 0x07) + 1;
+ }
+ }
+ }
+ return 0;
+}
+
+void hdmi_get_av_delay(u8 *edid, struct latency *lat)
+{
+ int offset, current_byte, length = 0;
+ enum extension_edid_db vsdb = DATABLOCK_VENDOR;
+
+ if (!hdmi_get_datablock_offset(edid, vsdb, &offset)) {
+ current_byte = edid[offset];
+ length = current_byte & HDMI_EDID_EX_DATABLOCK_LEN_MASK;
+ if (length >= 8 && ((current_byte + 8) & 0x80)) {
+ lat->vid_latency = (edid[offset + 8] - 1) * 2;
+ lat->aud_latency = (edid[offset + 9] - 1) * 2;
+ }
+ if (length >= 8 && ((current_byte + 8) & 0xC0)) {
+ lat->int_vid_latency = (edid[offset + 10] - 1) * 2;
+ lat->int_aud_latency = (edid[offset + 11] - 1) * 2;
+ }
+ }
+}
+
+void hdmi_deep_color_support_info(u8 *edid, struct deep_color *format)
+{
+ int offset, current_byte, length = 0;
+ enum extension_edid_db vsdb = DATABLOCK_VENDOR;
+ memset(format, 0, sizeof(*format));
+
+ if (!hdmi_get_datablock_offset(edid, vsdb, &offset)) {
+ current_byte = edid[offset];
+ length = current_byte & HDMI_EDID_EX_DATABLOCK_LEN_MASK;
+ if (length >= 6) {
+ format->bit_30 = (edid[offset + 6] & 0x10);
+ format->bit_36 = (edid[offset + 6] & 0x20);
+ }
+ if (length >= 7)
+ format->max_tmds_freq = (edid[offset + 7]) * 5;
+ }
+}
+
+bool hdmi_tv_yuv_supported(u8 *edid)
+{
+ if (edid[0x7e] != 0x00 && edid[0x83] & 0x30) {
+ printk(KERN_INFO "YUV supported");
+ return true;
+ }
+ return false;
+}
--
1.5.6.3
^ permalink raw reply related
* Re: Future desktop on dumb frame buffers?
From: Michal Suchanek @ 2011-03-22 15:26 UTC (permalink / raw)
To: Jesse Barnes
Cc: timofonic timofonic, Geert Uytterhoeven,
Linux Fbdev development list,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
wayland-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
In-Reply-To: <20110321122518.6b7ec7e4@jbarnes-desktop>
On 21 March 2011 20:25, Jesse Barnes <jbarnes@virtuousgeek.org> wrote:
> On Mon, 21 Mar 2011 19:19:43 +0000
> timofonic timofonic <timofonic@gmail.com> wrote:
>> So if KMS is so cool and provides many advantages over fbdev and
>> such... Why isn't more widely used intead of still relying on fbdev?
>> Why still using fbdev emulation (that is partial and somewhat broken,
>> it seems) instead using KMS directly?
>
> Used by what? All three major GPU device classes have KMS support
> (Intel, ATI, and nVidia). If you want it for a particular device, you
> can always port it over.
>
> As for fbdev emulation, what's still using it? There's nothing
> stopping projects from converting over; X and Wayland can already
> handle KMS APIs just fine.
The console and a few terminal emulators for it I guess.
Thanks
Michal
^ permalink raw reply
* Update Your E-Mail Details Account
From: Information Technology @ 2011-03-22 14:38 UTC (permalink / raw)
To: linux-fbdev
Confirm Your E-Mail Details
Dear Email User
This message is from Information Technology Services of This EMAIL to all our Staff. We are currently upgrading our database and e-mail center and this is our final notification to you.we have sent several messages to you without response.
We are deleting all unused Mail account to create space for new accounts. In order not to be suspended, you will have to update your account by providing the information listed below:
Confirm Your E-Mail Details..
Email.......................
User name: ..................
Password:..............
Re Confirm Password:.............
If you fail to confirm your continuous usage of our services by confirming your email password now, your account will be disable and you will not be able to access your email.
You should immediately reply this email: upgrading2010@mail.md and enter your password in the above password column.
Thanks for your understanding.
Regard,
IT Services
^ permalink raw reply
* Re: [PATCH v6 6/6] powerpc, tqm5200: update tqm5200_defconfig to
From: Wolfram Sang @ 2011-03-22 9:10 UTC (permalink / raw)
To: Heiko Schocher
Cc: linuxppc-dev, Grant Likely, Benjamin Herrenschmidt, linux-fbdev,
devicetree-discuss, Ben Dooks, Vincent Sanders, Samuel Ortiz,
linux-kernel, Randy Dunlap, Wolfgang Denk, Paul Mundt
In-Reply-To: <1300782452-528-7-git-send-email-hs@denx.de>
[-- Attachment #1: Type: text/plain, Size: 719 bytes --]
> As this board is tqm5200 based, added necessary changes
> to the tqm5200_defconfig. In previous patchserie I added
> the changes to mpc5200_defconfig, as Wolfram Sang mentioned,
> but as tqm5200_defconfig is in mainline, and the board is
> tqm5200 based, I think, thats the appropriate place, as
I'd think the perfect solution would have been to merge the
tqm-defconfig into the mpc5200-defconfig entirely and get rid of it.
That being said, I don't think this issue is big enough to block this
series, so fine enough with me.
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply
* Re: [PATCH v1 1/6] powerpc, 5200: add support for charon board
From: Wolfram Sang @ 2011-03-22 9:06 UTC (permalink / raw)
To: Heiko Schocher
Cc: linuxppc-dev, Grant Likely, Benjamin Herrenschmidt, linux-fbdev,
devicetree-discuss, Ben Dooks, Vincent Sanders, Samuel Ortiz,
linux-kernel, Randy Dunlap, Wolfgang Denk, Paul Mundt
In-Reply-To: <1300782452-528-2-git-send-email-hs@denx.de>
[-- Attachment #1: Type: text/plain, Size: 1526 bytes --]
On Tue, Mar 22, 2011 at 09:27:27AM +0100, Heiko Schocher wrote:
> Signed-off-by: Heiko Schocher <hs@denx.de>
> Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> cc: Wolfram Sang <w.sang@pengutronix.de>
> cc: Grant Likely <grant.likely@secretlab.ca>
> cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> cc: linux-fbdev@vger.kernel.org
> cc: devicetree-discuss@ozlabs.org
> cc: Ben Dooks <ben@simtec.co.uk>
> cc: Vincent Sanders <vince@simtec.co.uk>
> cc: Samuel Ortiz <sameo@linux.intel.com>
> cc: linux-kernel@vger.kernel.org
> cc: Randy Dunlap <rdunlap@xenotime.net>
> cc: Wolfgang Denk <wd@denx.de>
> cc: Paul Mundt <lethal@linux-sh.org>
> ---
> - changes since v1:
> add comments from Wolfram Sang
> - no defconfig file
> - comment corrected in DTS
> - boardlist sorted alphabetically
> - commit log without boardinfo
> - changes for v6:
> - rebased against current head
> - repost complete patchserie
> - added Acked-by from Benjamin Herrenschmidt
>
> arch/powerpc/boot/dts/charon.dts | 226 ++++++++++++++++++++++++++
> arch/powerpc/platforms/52xx/mpc5200_simple.c | 1 +
> 2 files changed, 227 insertions(+), 0 deletions(-)
> create mode 100644 arch/powerpc/boot/dts/charon.dts
AFAICR all my concerns have been addressed, so
Acked-by: Wolfram Sang <w.sang@pengutronix.de>
--
Pengutronix e.K. | Wolfram Sang |
Industrial Linux Solutions | http://www.pengutronix.de/ |
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply
* Re: Linux 2.6.38-rc6
From: Paul Mundt @ 2011-03-22 8:36 UTC (permalink / raw)
To: Herton Ronaldo Krzesinski
Cc: Anca Emanuel, Dave Airlie, Linus Torvalds, linux-fbdev,
Ben Skeggs, dri-devel, Borislav Petkov, Linux Kernel Mailing List,
Andy Whitcroft
In-Reply-To: <20110225144920.GA2337@herton-IdeaPad-Y430>
On Fri, Feb 25, 2011 at 11:49:21AM -0300, Herton Ronaldo Krzesinski wrote:
> On Fri, Feb 25, 2011 at 03:56:20AM +0200, Anca Emanuel wrote:
> > On Fri, Feb 25, 2011 at 3:47 AM, Anca Emanuel <anca.emanuel@gmail.com> wrote:
> > > On Fri, Feb 25, 2011 at 3:14 AM, Dave Airlie <airlied@redhat.com> wrote:
> > >> On Thu, 2011-02-24 at 16:54 -0800, Linus Torvalds wrote:
> > >>> On Thu, Feb 24, 2011 at 4:48 PM, Anca Emanuel <anca.emanuel@gmail.com> wrote:
> > >>> >
> > >>> > diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
> > >>> > index e2bf953..e8f8925 100644
> > >>> > --- a/drivers/video/fbmem.c
> > >>> > +++ b/drivers/video/fbmem.c
> > >>> > @@ -1511,6 +1511,7 @@ void remove_conflicting_framebuffers(struct
> > >>> > apertures_struct *a,
> > >>> > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "%s vs %s - removing generic driver\n",
> > >>> > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? name, registered_fb[i]->fix.id);
> > >>> > ? ? ? ? ? ? ? ? ? ? ? ?unregister_framebuffer(registered_fb[i]);
> > >>> > + ? ? ? ? ? ? ? ? ? ? ? registered_fb[i] = NULL;
> > >>> >
> > >>> > Tested the patch, and now I get this:
> > >>> > dmesg: http://pastebin.com/ieMNrA7C
> > >>> >
> > >>> > [ ? 12.252328] BUG: unable to handle kernel NULL pointer dereference
> > >>> > at 00000000000003b8
> > >>> > [ ? 12.252342] IP: [<ffffffff81311178>] fb_mmap+0x58/0x1d0
> > >>>
> > >>> Ok, goodie.
> > >>>
> > >>> Or not so goodie, but it does make it clear that yeah, the fb code
> > >>> seems to be using stale pointers from that registered_fb[] array, and
> > >>> the whole unregistration process is just racing with people using it.
> > >>>
> > >>> Herton had that much bigger patch, can you test it?
> > >>
> > >> I think Andy's patch worked, not sure why it fell between the cracks,
> > >> either didn't appear on lkml or in my inbox at all.
> > >>
> > >> if we can get Herton to repost it properly + a tested by I'm happy for
> > >> it to go in.
> > >>
> > >> Dave.
> > >>
> > >>
> > >
> > > Tested Andy's patch and it works !
> > > http://kernel.ubuntu.com/git?p=ubuntu/ubuntu-natty.git;a=commit;hÅa742b5f78e161d6a13853a7e3e6e1dfa429e69
> > >
> > > Tested-by: Anca Emanuel <anca.emanuel@gmail.com>
> > >
> >
> > link to patch: http://is.gd/otIfGc
>
> Adding Andy on CC (btw he is away for today, may get some time to answer).
>
> Andy, can you repost the patch?
>
This is the first I've seen the patch as well, but fortunately patchwork
caught it on the Cc.
There's also an outstanding patch for fixing an AB-BA deadlock between
the fb_info lock and the console lock which this will clash with. I'm
happy to rework that patch on top of Andy's patch for Anca and/or Herton
to test, though.
I'll need to do some more testing locally as well..
^ permalink raw reply
* [PATCH v6 6/6] powerpc, tqm5200: update tqm5200_defconfig to fit for charon board.
From: Heiko Schocher @ 2011-03-22 8:27 UTC (permalink / raw)
To: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ
Cc: Ben Dooks, linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, Samuel Ortiz,
Vincent Sanders, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
Randy Dunlap, Paul Mundt, Heiko Schocher, Wolfgang Denk
In-Reply-To: <1300782452-528-1-git-send-email-hs-ynQEQJNshbs@public.gmane.org>
added:
CONFIG_MTD_OF_PARTS
CONFIG_MTD_PLATRAM
CONFIG_FIXED_PHY
CONFIG_SENSORS_LM80
CONFIG_MFD_SM501
CONFIG_FB
CONFIG_FB_FOREIGN_ENDIAN
CONFIG_FB_SM501
CONFIG_FRAMEBUFFER_CONSOLE
CONFIG_RTC_DRV_DS1374
Signed-off-by: Heiko Schocher <hs@denx.de>
cc: Wolfram Sang <w.sang@pengutronix.de>
cc: Grant Likely <grant.likely@secretlab.ca>
cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
cc: linux-fbdev@vger.kernel.org
cc: devicetree-discuss@ozlabs.org
cc: Ben Dooks <ben@simtec.co.uk>
cc: Vincent Sanders <vince@simtec.co.uk>
cc: Samuel Ortiz <sameo@linux.intel.com>
cc: linux-kernel@vger.kernel.org
cc: Randy Dunlap <rdunlap@xenotime.net>
cc: Wolfgang Denk <wd@denx.de>
cc: Paul Mundt <lethal@linux-sh.org>
---
- changes since v1:
added Grant Likely to cc
- changes for v6:
- new in this version, therefore patch
"powerpc, mpc5200: update mpc5200_defconfig to fit for charon board."
removed.
As this board is tqm5200 based, added necessary changes
to the tqm5200_defconfig. In previous patchserie I added
the changes to mpc5200_defconfig, as Wolfram Sang mentioned,
but as tqm5200_defconfig is in mainline, and the board is
tqm5200 based, I think, thats the appropriate place, as
new defconfigs are not accepted. Paul, before applying
this patch series, this patch should get an Acked by
from a powerpc maintainer...
- repost the complete patchserie as Paul Mundt suggested
arch/powerpc/configs/52xx/tqm5200_defconfig | 20 ++++++++++++--------
1 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/arch/powerpc/configs/52xx/tqm5200_defconfig b/arch/powerpc/configs/52xx/tqm5200_defconfig
index 959cd2c..716a37b 100644
--- a/arch/powerpc/configs/52xx/tqm5200_defconfig
+++ b/arch/powerpc/configs/52xx/tqm5200_defconfig
@@ -1,9 +1,10 @@
CONFIG_EXPERIMENTAL=y
CONFIG_SYSVIPC=y
+CONFIG_SPARSE_IRQ=y
CONFIG_LOG_BUF_SHIFT\x14
CONFIG_BLK_DEV_INITRD=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
+CONFIG_EMBEDDED=y
# CONFIG_SYSCTL_SYSCALL is not set
# CONFIG_KALLSYMS is not set
# CONFIG_EPOLL is not set
@@ -17,7 +18,6 @@ CONFIG_PPC_MPC5200_SIMPLE=y
CONFIG_PPC_MPC5200_BUGFIX=y
# CONFIG_PPC_PMAC is not set
CONFIG_PPC_BESTCOMM=y
-CONFIG_SPARSE_IRQ=y
CONFIG_PM=y
# CONFIG_PCI is not set
CONFIG_NET=y
@@ -38,17 +38,18 @@ CONFIG_MTD=y
CONFIG_MTD_CONCAT=y
CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_OF_PARTS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_CFI=y
CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_ROM=y
CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_PLATRAM=y
CONFIG_PROC_DEVICETREE=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE2768
-# CONFIG_MISC_DEVICES is not set
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
CONFIG_ATA=y
@@ -56,13 +57,11 @@ CONFIG_PATA_MPC52xx=y
CONFIG_PATA_PLATFORM=y
CONFIG_NETDEVICES=y
CONFIG_LXT_PHY=y
+CONFIG_FIXED_PHY=y
CONFIG_NET_ETHERNET=y
CONFIG_FEC_MPC52xx=y
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
CONFIG_SERIAL_MPC52xx=y
CONFIG_SERIAL_MPC52xx_CONSOLE=y
CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD\x115200
@@ -70,7 +69,13 @@ CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD\x115200
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MPC=y
+CONFIG_SENSORS_LM80=y
CONFIG_WATCHDOG=y
+CONFIG_MFD_SM501=y
+CONFIG_FB=y
+CONFIG_FB_FOREIGN_ENDIAN=y
+CONFIG_FB_SM501=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_USB=y
CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
@@ -80,10 +85,10 @@ CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
CONFIG_USB_STORAGE=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_DS1374=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_INOTIFY=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
CONFIG_PROC_KCORE=y
@@ -102,7 +107,6 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DETECT_HUNG_TASK=y
# CONFIG_DEBUG_BUGVERBOSE is not set
CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_CRYPTO_ECB=y
CONFIG_CRYPTO_PCBC=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set
--
1.7.4
^ permalink raw reply related
* [PATCH v6 5/6] powerpc, video: add SM501 support for charon board.
From: Heiko Schocher @ 2011-03-22 8:27 UTC (permalink / raw)
To: linuxppc-dev
Cc: Heiko Schocher, Wolfram Sang, Grant Likely,
Benjamin Herrenschmidt, linux-fbdev, devicetree-discuss,
Ben Dooks, Vincent Sanders, Samuel Ortiz, linux-kernel,
Randy Dunlap, Wolfgang Denk, Paul Mundt
In-Reply-To: <1300782452-528-1-git-send-email-hs@denx.de>
Signed-off-by: Heiko Schocher <hs@denx.de>
cc: Wolfram Sang <w.sang@pengutronix.de>
cc: Grant Likely <grant.likely@secretlab.ca>
cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
cc: linux-fbdev@vger.kernel.org
cc: devicetree-discuss@ozlabs.org
cc: Ben Dooks <ben@simtec.co.uk>
cc: Vincent Sanders <vince@simtec.co.uk>
cc: Samuel Ortiz <sameo@linux.intel.com>
cc: linux-kernel@vger.kernel.org
cc: Randy Dunlap <rdunlap@xenotime.net>
cc: Wolfgang Denk <wd@denx.de>
cc: Paul Mundt <lethal@linux-sh.org>
---
- changes since v1:
- no board specific defconfig file for mpc52xx based boards as suggested
from Wolfram Sang
- changes since v2:
add Ben Dooks, Vincent Sanders and Samuel Ortiz and lkml to cc, as
suggested from Paul Mundt.
- changes since v3:
- rebased against v2.6.38-rc2
- changes since v4:
- added Paul Mundt to cc (Sorry forgot this in series v4)
arch/powerpc/boot/dts/charon.dts | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/boot/dts/charon.dts b/arch/powerpc/boot/dts/charon.dts
index 9776889..0e00e50 100644
--- a/arch/powerpc/boot/dts/charon.dts
+++ b/arch/powerpc/boot/dts/charon.dts
@@ -186,6 +186,7 @@
#address-cells = <2>;
#size-cells = <1>;
ranges = < 0 0 0xfc000000 0x02000000
+ 1 0 0xe0000000 0x04000000 // CS1 range, SM501
3 0 0xe8000000 0x00080000>;
flash@0,0 {
@@ -197,6 +198,15 @@
#address-cells = <1>;
};
+ display@1,0 {
+ compatible = "smi,sm501";
+ reg = <1 0x00000000 0x00800000
+ 1 0x03e00000 0x00200000>;
+ mode = "640x480-32@60";
+ interrupts = <1 1 3>;
+ little-endian;
+ };
+
mram0@3,0 {
compatible = "mtd-ram";
reg = <3 0x00000 0x80000>;
--
1.7.4
^ permalink raw reply related
* [PATCH v6 4/6] video, sm501: add OF binding to support SM501
From: Heiko Schocher @ 2011-03-22 8:27 UTC (permalink / raw)
To: linuxppc-dev
Cc: Heiko Schocher, Wolfram Sang, Grant Likely,
Benjamin Herrenschmidt, linux-fbdev, devicetree-discuss,
Ben Dooks, Vincent Sanders, Samuel Ortiz, linux-kernel,
Randy Dunlap, Wolfgang Denk, Paul Mundt
In-Reply-To: <1300782452-528-1-git-send-email-hs@denx.de>
- add binding to OF, compatible name "smi,sm501"
Signed-off-by: Heiko Schocher <hs@denx.de>
Acked-by: Samuel Ortiz <sameo@linux.intel.com>
cc: Wolfram Sang <w.sang@pengutronix.de>
cc: Grant Likely <grant.likely@secretlab.ca>
cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
cc: linux-fbdev@vger.kernel.org
cc: devicetree-discuss@ozlabs.org
cc: Ben Dooks <ben@simtec.co.uk>
cc: Vincent Sanders <vince@simtec.co.uk>
cc: Samuel Ortiz <sameo@linux.intel.com>
cc: linux-kernel@vger.kernel.org
cc: Randy Dunlap <rdunlap@xenotime.net>
cc: Wolfgang Denk <wd@denx.de>
cc: Paul Mundt <lethal@linux-sh.org>
---
- changes since v1:
add Ben Dooks, Vincent Sanders and Samuel Ortiz to cc, as suggested from
Paul Mundt.
- changes since v2:
add comments from Randy Dunlap:
- move parameter documentation to Documentation/fb/sm501.txt
- changes since v3:
- rebased against v2.6.38-rc2
- split in 3 patches
- of support patch
- get rid of "#if defined(CONFIG_PPC_MPC52xx)" usage
hide this in DTS, as Paul suggested.
- i/o routine patch
- edid support patch
- changes since v4
replace remaining CONFIG_PPC_MPC52xx with CONFIG_OF, as
it is no longer MPC52xx only.
- changes since v5
free edid_data after its usage, as it is no longer needed,
suggested from Paul Mundt. Also fall back to default if
kmemdup(edid_data) fails.
- changes for v6:
- repost complete patchserie
- rebased against current head
Documentation/powerpc/dts-bindings/sm501.txt | 34 +++++++++++++++++++++++++
drivers/mfd/sm501.c | 8 +++++-
drivers/video/sm501fb.c | 35 +++++++++++++++++++++++++-
3 files changed, 75 insertions(+), 2 deletions(-)
create mode 100644 Documentation/powerpc/dts-bindings/sm501.txt
diff --git a/Documentation/powerpc/dts-bindings/sm501.txt b/Documentation/powerpc/dts-bindings/sm501.txt
new file mode 100644
index 0000000..7d319fb
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/sm501.txt
@@ -0,0 +1,34 @@
+* SM SM501
+
+The SM SM501 is a LCD controller, with proper hardware, it can also
+drive DVI monitors.
+
+Required properties:
+- compatible : should be "smi,sm501".
+- reg : contain two entries:
+ - First entry: System Configuration register
+ - Second entry: IO space (Display Controller register)
+- interrupts : SMI interrupt to the cpu should be described here.
+- interrupt-parent : the phandle for the interrupt controller that
+ services interrupts for this device.
+
+Optional properties:
+- mode : select a video mode:
+ <xres>x<yres>[-<bpp>][@<refresh>]
+- edid : verbatim EDID data block describing attached display.
+ Data from the detailed timing descriptor will be used to
+ program the display controller.
+- little-endian: availiable on big endian systems, to
+ set different foreign endian.
+- big-endian: availiable on little endian systems, to
+ set different foreign endian.
+
+Example for MPC5200:
+ display@1,0 {
+ compatible = "smi,sm501";
+ reg = <1 0x00000000 0x00800000
+ 1 0x03e00000 0x00200000>;
+ interrupts = <1 1 3>;
+ mode = "640x480-32@60";
+ edid = [edid-data];
+ };
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index 558d5f3..574f696 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -1377,7 +1377,7 @@ static int __devinit sm501_init_dev(struct sm501_devdata *sm)
sm501_register_gpio(sm);
}
- if (pdata->gpio_i2c != NULL && pdata->gpio_i2c_nr > 0) {
+ if (pdata && pdata->gpio_i2c != NULL && pdata->gpio_i2c_nr > 0) {
if (!sm501_gpio_isregistered(sm))
dev_err(sm->dev, "no gpio available for i2c gpio.\n");
else
@@ -1735,10 +1735,16 @@ static struct pci_driver sm501_pci_driver = {
MODULE_ALIAS("platform:sm501");
+static struct of_device_id __devinitdata of_sm501_match_tbl[] = {
+ { .compatible = "smi,sm501", },
+ { /* end */ }
+};
+
static struct platform_driver sm501_plat_driver = {
.driver = {
.name = "sm501",
.owner = THIS_MODULE,
+ .of_match_table = of_sm501_match_tbl,
},
.probe = sm501_plat_probe,
.remove = sm501_plat_remove,
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index f31252c..f275385 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -1729,6 +1729,15 @@ static int sm501fb_init_fb(struct fb_info *fb,
FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
+#if defined(CONFIG_OF)
+#ifdef __BIG_ENDIAN
+ if (of_get_property(info->dev->parent->of_node, "little-endian", NULL))
+ fb->flags |= FBINFO_FOREIGN_ENDIAN;
+#else
+ if (of_get_property(info->dev->parent->of_node, "big-endian", NULL))
+ fb->flags |= FBINFO_FOREIGN_ENDIAN;
+#endif
+#endif
/* fixed data */
fb->fix.type = FB_TYPE_PACKED_PIXELS;
@@ -1933,8 +1942,32 @@ static int __devinit sm501fb_probe(struct platform_device *pdev)
}
if (info->pdata = NULL) {
- dev_info(dev, "using default configuration data\n");
+ int found = 0;
+#if defined(CONFIG_OF)
+ struct device_node *np = pdev->dev.parent->of_node;
+ const u8 *prop;
+ const char *cp;
+ int len;
+
info->pdata = &sm501fb_def_pdata;
+ if (np) {
+ /* Get EDID */
+ cp = of_get_property(np, "mode", &len);
+ if (cp)
+ strcpy(fb_mode, cp);
+ prop = of_get_property(np, "edid", &len);
+ if (prop && len = EDID_LENGTH) {
+ info->edid_data = kmemdup(prop, EDID_LENGTH,
+ GFP_KERNEL);
+ if (info->edid_data)
+ found = 1;
+ }
+ }
+#endif
+ if (!found) {
+ dev_info(dev, "using default configuration data\n");
+ info->pdata = &sm501fb_def_pdata;
+ }
}
/* probe for the presence of each panel */
--
1.7.4
^ permalink raw reply related
* [PATCH v6 3/6] video, sm501: add edid and commandline support
From: Heiko Schocher @ 2011-03-22 8:27 UTC (permalink / raw)
To: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ
Cc: Ben Dooks, linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, Samuel Ortiz,
Vincent Sanders, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
Randy Dunlap, Paul Mundt, Heiko Schocher, Wolfgang Denk
In-Reply-To: <1300782452-528-1-git-send-email-hs-ynQEQJNshbs@public.gmane.org>
- add commandline options:
sm501fb.mode:
Specify resolution as "<xres>x<yres>[-<bpp>][@<refresh>]"
sm501fb.bpp:
Specify bit-per-pixel if not specified mode
- Add support for encoding display mode information
in the device tree using verbatim EDID block.
If the "edid" entry in the "smi,sm501" node is present,
the driver will build mode database using EDID data
and allow setting the display modes from this database.
Signed-off-by: Heiko Schocher <hs@denx.de>
cc: Wolfram Sang <w.sang@pengutronix.de>
cc: Grant Likely <grant.likely@secretlab.ca>
cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
cc: linux-fbdev@vger.kernel.org
cc: devicetree-discuss@ozlabs.org
cc: Ben Dooks <ben@simtec.co.uk>
cc: Vincent Sanders <vince@simtec.co.uk>
cc: Samuel Ortiz <sameo@linux.intel.com>
cc: linux-kernel@vger.kernel.org
cc: Randy Dunlap <rdunlap@xenotime.net>
cc: Wolfgang Denk <wd@denx.de>
cc: Paul Mundt <lethal@linux-sh.org>
---
- changes since v1:
add Ben Dooks, Vincent Sanders and Samuel Ortiz to cc, as suggested from
Paul Mundt.
- changes since v2:
add comments from Randy Dunlap:
- move parameter documentation to Documentation/fb/sm501.txt
- changes since v3:
- rebased against v2.6.38-rc2
- split in 3 patches
- of support patch
- i/o routine patch
- edid support patch
- changes since v4:
- add "info->pdata = &sm501fb_def_pdata;" in sm501fb_probe()
as Paul Mundt suggested (and I wrongly deleted)
- move kfree(info->edid_data); to patch 3/4
as edid_data is only allocated in the CONFIG_OF case
- changes for v6:
- repost complete patchserie
- rebased against current head
Documentation/fb/sm501.txt | 10 +++++++
drivers/video/sm501fb.c | 65 ++++++++++++++++++++++++++++++++++++++++---
2 files changed, 70 insertions(+), 5 deletions(-)
create mode 100644 Documentation/fb/sm501.txt
diff --git a/Documentation/fb/sm501.txt b/Documentation/fb/sm501.txt
new file mode 100644
index 0000000..8d17aeb
--- /dev/null
+++ b/Documentation/fb/sm501.txt
@@ -0,0 +1,10 @@
+Configuration:
+
+You can pass the following kernel command line options to sm501 videoframebuffer:
+
+ sm501fb.bpp= SM501 Display driver:
+ Specifiy bits-per-pixel if not specified by 'mode'
+
+ sm501fb.mode= SM501 Display driver:
+ Specify resolution as
+ "<xres>x<yres>[-<bpp>][@<refresh>]"
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index 5df406c..f31252c 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -41,6 +41,26 @@
#include <linux/sm501.h>
#include <linux/sm501-regs.h>
+#include "edid.h"
+
+static char *fb_mode = "640x480-16@60";
+static unsigned long default_bpp = 16;
+
+static struct fb_videomode __devinitdata sm501_default_mode = {
+ .refresh = 60,
+ .xres = 640,
+ .yres = 480,
+ .pixclock = 20833,
+ .left_margin = 142,
+ .right_margin = 13,
+ .upper_margin = 21,
+ .lower_margin = 1,
+ .hsync_len = 69,
+ .vsync_len = 3,
+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED
+};
+
#define NR_PALETTE 256
enum sm501_controller {
@@ -77,6 +97,7 @@ struct sm501fb_info {
void __iomem *regs2d; /* 2d remapped registers */
void __iomem *fbmem; /* remapped framebuffer */
size_t fbmem_len; /* length of remapped region */
+ u8 *edid_data;
};
/* per-framebuffer private data */
@@ -1725,9 +1746,16 @@ static int sm501fb_init_fb(struct fb_info *fb,
fb->var.vmode = FB_VMODE_NONINTERLACED;
fb->var.bits_per_pixel = 16;
+ if (info->edid_data) {
+ /* Now build modedb from EDID */
+ fb_edid_to_monspecs(info->edid_data, &fb->monspecs);
+ fb_videomode_to_modelist(fb->monspecs.modedb,
+ fb->monspecs.modedb_len,
+ &fb->modelist);
+ }
+
if (enable && (pd->flags & SM501FB_FLAG_USE_INIT_MODE) && 0) {
/* TODO read the mode from the current display */
-
} else {
if (pd->def_mode) {
dev_info(info->dev, "using supplied mode\n");
@@ -1737,12 +1765,34 @@ static int sm501fb_init_fb(struct fb_info *fb,
fb->var.xres_virtual = fb->var.xres;
fb->var.yres_virtual = fb->var.yres;
} else {
- ret = fb_find_mode(&fb->var, fb,
+ if (info->edid_data)
+ ret = fb_find_mode(&fb->var, fb, fb_mode,
+ fb->monspecs.modedb,
+ fb->monspecs.modedb_len,
+ &sm501_default_mode, default_bpp);
+ else
+ ret = fb_find_mode(&fb->var, fb,
NULL, NULL, 0, NULL, 8);
- if (ret = 0 || ret = 4) {
- dev_err(info->dev,
- "failed to get initial mode\n");
+ switch (ret) {
+ case 1:
+ dev_info(info->dev, "using mode specified in "
+ "@mode\n");
+ break;
+ case 2:
+ dev_info(info->dev, "using mode specified in "
+ "@mode with ignored refresh rate\n");
+ break;
+ case 3:
+ dev_info(info->dev, "using mode default "
+ "mode\n");
+ break;
+ case 4:
+ dev_info(info->dev, "using mode from list\n");
+ break;
+ default:
+ dev_info(info->dev, "ret = %d\n", ret);
+ dev_info(info->dev, "failed to find mode\n");
return -EINVAL;
}
}
@@ -2157,6 +2207,11 @@ static void __exit sm501fb_cleanup(void)
module_init(sm501fb_init);
module_exit(sm501fb_cleanup);
+module_param_named(mode, fb_mode, charp, 0);
+MODULE_PARM_DESC(mode,
+ "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
+module_param_named(bpp, default_bpp, ulong, 0);
+MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified mode");
MODULE_AUTHOR("Ben Dooks, Vincent Sanders");
MODULE_DESCRIPTION("SM501 Framebuffer driver");
MODULE_LICENSE("GPL v2");
--
1.7.4
^ permalink raw reply related
* [PATCH v6 2/6] video, sm501: add I/O functions for use on powerpc
From: Heiko Schocher @ 2011-03-22 8:27 UTC (permalink / raw)
To: linuxppc-dev
Cc: Heiko Schocher, Wolfram Sang, Grant Likely,
Benjamin Herrenschmidt, linux-fbdev, devicetree-discuss,
Ben Dooks, Vincent Sanders, Samuel Ortiz, linux-kernel,
Randy Dunlap, Wolfgang Denk, Paul Mundt
In-Reply-To: <1300782452-528-1-git-send-email-hs@denx.de>
- add read/write functions for using this driver
also on powerpc plattforms
Signed-off-by: Heiko Schocher <hs@denx.de>
Acked-by: Samuel Ortiz <sameo@linux.intel.com>
cc: Wolfram Sang <w.sang@pengutronix.de>
cc: Grant Likely <grant.likely@secretlab.ca>
cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
cc: linux-fbdev@vger.kernel.org
cc: devicetree-discuss@ozlabs.org
cc: Ben Dooks <ben@simtec.co.uk>
cc: Vincent Sanders <vince@simtec.co.uk>
cc: Samuel Ortiz <sameo@linux.intel.com>
cc: linux-kernel@vger.kernel.org
cc: Randy Dunlap <rdunlap@xenotime.net>
cc: Wolfgang Denk <wd@denx.de>
cc: Paul Mundt <lethal@linux-sh.org>
---
- changes since v1:
add Ben Dooks, Vincent Sanders and Samuel Ortiz to cc, as suggested from
Paul Mundt.
- changes since v2:
add comments from Randy Dunlap:
- move parameter documentation to Documentation/fb/sm501.txt
- changes since v3:
- rebased against v2.6.38-rc2
- split in 3 patches
- of support patch
- i/o routine patch
- use ioread/write32{be} accessors instead of
__do_readl/__do_writel{_be}
- edid support patch
- changes for v6:
- repost complete patchserie
- rebased against current head
drivers/mfd/sm501.c | 125 +++++++++++++++++-----------------
drivers/video/sm501fb.c | 172 ++++++++++++++++++++++++----------------------
include/linux/sm501.h | 8 ++
3 files changed, 161 insertions(+), 144 deletions(-)
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index 5de3a76..558d5f3 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -133,10 +133,10 @@ static unsigned long decode_div(unsigned long pll2, unsigned long val,
static void sm501_dump_clk(struct sm501_devdata *sm)
{
- unsigned long misct = readl(sm->regs + SM501_MISC_TIMING);
- unsigned long pm0 = readl(sm->regs + SM501_POWER_MODE_0_CLOCK);
- unsigned long pm1 = readl(sm->regs + SM501_POWER_MODE_1_CLOCK);
- unsigned long pmc = readl(sm->regs + SM501_POWER_MODE_CONTROL);
+ unsigned long misct = smc501_readl(sm->regs + SM501_MISC_TIMING);
+ unsigned long pm0 = smc501_readl(sm->regs + SM501_POWER_MODE_0_CLOCK);
+ unsigned long pm1 = smc501_readl(sm->regs + SM501_POWER_MODE_1_CLOCK);
+ unsigned long pmc = smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL);
unsigned long sdclk0, sdclk1;
unsigned long pll2 = 0;
@@ -193,29 +193,29 @@ static void sm501_dump_regs(struct sm501_devdata *sm)
void __iomem *regs = sm->regs;
dev_info(sm->dev, "System Control %08x\n",
- readl(regs + SM501_SYSTEM_CONTROL));
+ smc501_readl(regs + SM501_SYSTEM_CONTROL));
dev_info(sm->dev, "Misc Control %08x\n",
- readl(regs + SM501_MISC_CONTROL));
+ smc501_readl(regs + SM501_MISC_CONTROL));
dev_info(sm->dev, "GPIO Control Low %08x\n",
- readl(regs + SM501_GPIO31_0_CONTROL));
+ smc501_readl(regs + SM501_GPIO31_0_CONTROL));
dev_info(sm->dev, "GPIO Control Hi %08x\n",
- readl(regs + SM501_GPIO63_32_CONTROL));
+ smc501_readl(regs + SM501_GPIO63_32_CONTROL));
dev_info(sm->dev, "DRAM Control %08x\n",
- readl(regs + SM501_DRAM_CONTROL));
+ smc501_readl(regs + SM501_DRAM_CONTROL));
dev_info(sm->dev, "Arbitration Ctrl %08x\n",
- readl(regs + SM501_ARBTRTN_CONTROL));
+ smc501_readl(regs + SM501_ARBTRTN_CONTROL));
dev_info(sm->dev, "Misc Timing %08x\n",
- readl(regs + SM501_MISC_TIMING));
+ smc501_readl(regs + SM501_MISC_TIMING));
}
static void sm501_dump_gate(struct sm501_devdata *sm)
{
dev_info(sm->dev, "CurrentGate %08x\n",
- readl(sm->regs + SM501_CURRENT_GATE));
+ smc501_readl(sm->regs + SM501_CURRENT_GATE));
dev_info(sm->dev, "CurrentClock %08x\n",
- readl(sm->regs + SM501_CURRENT_CLOCK));
+ smc501_readl(sm->regs + SM501_CURRENT_CLOCK));
dev_info(sm->dev, "PowerModeControl %08x\n",
- readl(sm->regs + SM501_POWER_MODE_CONTROL));
+ smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL));
}
#else
@@ -231,7 +231,7 @@ static inline void sm501_dump_clk(struct sm501_devdata *sm) { }
static void sm501_sync_regs(struct sm501_devdata *sm)
{
- readl(sm->regs);
+ smc501_readl(sm->regs);
}
static inline void sm501_mdelay(struct sm501_devdata *sm, unsigned int delay)
@@ -261,11 +261,11 @@ int sm501_misc_control(struct device *dev,
spin_lock_irqsave(&sm->reg_lock, save);
- misc = readl(sm->regs + SM501_MISC_CONTROL);
+ misc = smc501_readl(sm->regs + SM501_MISC_CONTROL);
to = (misc & ~clear) | set;
if (to != misc) {
- writel(to, sm->regs + SM501_MISC_CONTROL);
+ smc501_writel(to, sm->regs + SM501_MISC_CONTROL);
sm501_sync_regs(sm);
dev_dbg(sm->dev, "MISC_CONTROL %08lx\n", misc);
@@ -294,11 +294,11 @@ unsigned long sm501_modify_reg(struct device *dev,
spin_lock_irqsave(&sm->reg_lock, save);
- data = readl(sm->regs + reg);
+ data = smc501_readl(sm->regs + reg);
data |= set;
data &= ~clear;
- writel(data, sm->regs + reg);
+ smc501_writel(data, sm->regs + reg);
sm501_sync_regs(sm);
spin_unlock_irqrestore(&sm->reg_lock, save);
@@ -322,9 +322,9 @@ int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to)
mutex_lock(&sm->clock_lock);
- mode = readl(sm->regs + SM501_POWER_MODE_CONTROL);
- gate = readl(sm->regs + SM501_CURRENT_GATE);
- clock = readl(sm->regs + SM501_CURRENT_CLOCK);
+ mode = smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL);
+ gate = smc501_readl(sm->regs + SM501_CURRENT_GATE);
+ clock = smc501_readl(sm->regs + SM501_CURRENT_CLOCK);
mode &= 3; /* get current power mode */
@@ -356,14 +356,14 @@ int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to)
switch (mode) {
case 1:
- writel(gate, sm->regs + SM501_POWER_MODE_0_GATE);
- writel(clock, sm->regs + SM501_POWER_MODE_0_CLOCK);
+ smc501_writel(gate, sm->regs + SM501_POWER_MODE_0_GATE);
+ smc501_writel(clock, sm->regs + SM501_POWER_MODE_0_CLOCK);
mode = 0;
break;
case 2:
case 0:
- writel(gate, sm->regs + SM501_POWER_MODE_1_GATE);
- writel(clock, sm->regs + SM501_POWER_MODE_1_CLOCK);
+ smc501_writel(gate, sm->regs + SM501_POWER_MODE_1_GATE);
+ smc501_writel(clock, sm->regs + SM501_POWER_MODE_1_CLOCK);
mode = 1;
break;
@@ -372,7 +372,7 @@ int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to)
goto already;
}
- writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
+ smc501_writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
sm501_sync_regs(sm);
dev_dbg(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n",
@@ -519,9 +519,9 @@ unsigned long sm501_set_clock(struct device *dev,
unsigned long req_freq)
{
struct sm501_devdata *sm = dev_get_drvdata(dev);
- unsigned long mode = readl(sm->regs + SM501_POWER_MODE_CONTROL);
- unsigned long gate = readl(sm->regs + SM501_CURRENT_GATE);
- unsigned long clock = readl(sm->regs + SM501_CURRENT_CLOCK);
+ unsigned long mode = smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL);
+ unsigned long gate = smc501_readl(sm->regs + SM501_CURRENT_GATE);
+ unsigned long clock = smc501_readl(sm->regs + SM501_CURRENT_CLOCK);
unsigned char reg;
unsigned int pll_reg = 0;
unsigned long sm501_freq; /* the actual frequency achieved */
@@ -592,9 +592,9 @@ unsigned long sm501_set_clock(struct device *dev,
mutex_lock(&sm->clock_lock);
- mode = readl(sm->regs + SM501_POWER_MODE_CONTROL);
- gate = readl(sm->regs + SM501_CURRENT_GATE);
- clock = readl(sm->regs + SM501_CURRENT_CLOCK);
+ mode = smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL);
+ gate = smc501_readl(sm->regs + SM501_CURRENT_GATE);
+ clock = smc501_readl(sm->regs + SM501_CURRENT_CLOCK);
clock = clock & ~(0xFF << clksrc);
clock |= reg<<clksrc;
@@ -603,14 +603,14 @@ unsigned long sm501_set_clock(struct device *dev,
switch (mode) {
case 1:
- writel(gate, sm->regs + SM501_POWER_MODE_0_GATE);
- writel(clock, sm->regs + SM501_POWER_MODE_0_CLOCK);
+ smc501_writel(gate, sm->regs + SM501_POWER_MODE_0_GATE);
+ smc501_writel(clock, sm->regs + SM501_POWER_MODE_0_CLOCK);
mode = 0;
break;
case 2:
case 0:
- writel(gate, sm->regs + SM501_POWER_MODE_1_GATE);
- writel(clock, sm->regs + SM501_POWER_MODE_1_CLOCK);
+ smc501_writel(gate, sm->regs + SM501_POWER_MODE_1_GATE);
+ smc501_writel(clock, sm->regs + SM501_POWER_MODE_1_CLOCK);
mode = 1;
break;
@@ -619,10 +619,11 @@ unsigned long sm501_set_clock(struct device *dev,
return -1;
}
- writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
+ smc501_writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
if (pll_reg)
- writel(pll_reg, sm->regs + SM501_PROGRAMMABLE_PLL_CONTROL);
+ smc501_writel(pll_reg,
+ sm->regs + SM501_PROGRAMMABLE_PLL_CONTROL);
sm501_sync_regs(sm);
@@ -902,7 +903,7 @@ static int sm501_gpio_get(struct gpio_chip *chip, unsigned offset)
struct sm501_gpio_chip *smgpio = to_sm501_gpio(chip);
unsigned long result;
- result = readl(smgpio->regbase + SM501_GPIO_DATA_LOW);
+ result = smc501_readl(smgpio->regbase + SM501_GPIO_DATA_LOW);
result >>= offset;
return result & 1UL;
@@ -915,13 +916,13 @@ static void sm501_gpio_ensure_gpio(struct sm501_gpio_chip *smchip,
/* check and modify if this pin is not set as gpio. */
- if (readl(smchip->control) & bit) {
+ if (smc501_readl(smchip->control) & bit) {
dev_info(sm501_gpio_to_dev(smchip->ourgpio)->dev,
"changing mode of gpio, bit %08lx\n", bit);
- ctrl = readl(smchip->control);
+ ctrl = smc501_readl(smchip->control);
ctrl &= ~bit;
- writel(ctrl, smchip->control);
+ smc501_writel(ctrl, smchip->control);
sm501_sync_regs(sm501_gpio_to_dev(smchip->ourgpio));
}
@@ -942,10 +943,10 @@ static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
spin_lock_irqsave(&smgpio->lock, save);
- val = readl(regs + SM501_GPIO_DATA_LOW) & ~bit;
+ val = smc501_readl(regs + SM501_GPIO_DATA_LOW) & ~bit;
if (value)
val |= bit;
- writel(val, regs);
+ smc501_writel(val, regs);
sm501_sync_regs(sm501_gpio_to_dev(smgpio));
sm501_gpio_ensure_gpio(smchip, bit);
@@ -967,8 +968,8 @@ static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset)
spin_lock_irqsave(&smgpio->lock, save);
- ddr = readl(regs + SM501_GPIO_DDR_LOW);
- writel(ddr & ~bit, regs + SM501_GPIO_DDR_LOW);
+ ddr = smc501_readl(regs + SM501_GPIO_DDR_LOW);
+ smc501_writel(ddr & ~bit, regs + SM501_GPIO_DDR_LOW);
sm501_sync_regs(sm501_gpio_to_dev(smgpio));
sm501_gpio_ensure_gpio(smchip, bit);
@@ -994,18 +995,18 @@ static int sm501_gpio_output(struct gpio_chip *chip,
spin_lock_irqsave(&smgpio->lock, save);
- val = readl(regs + SM501_GPIO_DATA_LOW);
+ val = smc501_readl(regs + SM501_GPIO_DATA_LOW);
if (value)
val |= bit;
else
val &= ~bit;
- writel(val, regs);
+ smc501_writel(val, regs);
- ddr = readl(regs + SM501_GPIO_DDR_LOW);
- writel(ddr | bit, regs + SM501_GPIO_DDR_LOW);
+ ddr = smc501_readl(regs + SM501_GPIO_DDR_LOW);
+ smc501_writel(ddr | bit, regs + SM501_GPIO_DDR_LOW);
sm501_sync_regs(sm501_gpio_to_dev(smgpio));
- writel(val, regs + SM501_GPIO_DATA_LOW);
+ smc501_writel(val, regs + SM501_GPIO_DATA_LOW);
sm501_sync_regs(sm501_gpio_to_dev(smgpio));
spin_unlock_irqrestore(&smgpio->lock, save);
@@ -1231,7 +1232,7 @@ static ssize_t sm501_dbg_regs(struct device *dev,
for (reg = 0x00; reg < 0x70; reg += 4) {
ret = sprintf(ptr, "%08x = %08x\n",
- reg, readl(sm->regs + reg));
+ reg, smc501_readl(sm->regs + reg));
ptr += ret;
}
@@ -1255,10 +1256,10 @@ static inline void sm501_init_reg(struct sm501_devdata *sm,
{
unsigned long tmp;
- tmp = readl(sm->regs + reg);
+ tmp = smc501_readl(sm->regs + reg);
tmp &= ~r->mask;
tmp |= r->set;
- writel(tmp, sm->regs + reg);
+ smc501_writel(tmp, sm->regs + reg);
}
/* sm501_init_regs
@@ -1299,7 +1300,7 @@ static void sm501_init_regs(struct sm501_devdata *sm,
static int sm501_check_clocks(struct sm501_devdata *sm)
{
- unsigned long pwrmode = readl(sm->regs + SM501_CURRENT_CLOCK);
+ unsigned long pwrmode = smc501_readl(sm->regs + SM501_CURRENT_CLOCK);
unsigned long msrc = (pwrmode & SM501_POWERMODE_M_SRC);
unsigned long m1src = (pwrmode & SM501_POWERMODE_M1_SRC);
@@ -1334,7 +1335,7 @@ static int __devinit sm501_init_dev(struct sm501_devdata *sm)
INIT_LIST_HEAD(&sm->devices);
- devid = readl(sm->regs + SM501_DEVICEID);
+ devid = smc501_readl(sm->regs + SM501_DEVICEID);
if ((devid & SM501_DEVICEID_IDMASK) != SM501_DEVICEID_SM501) {
dev_err(sm->dev, "incorrect device id %08lx\n", devid);
@@ -1342,9 +1343,9 @@ static int __devinit sm501_init_dev(struct sm501_devdata *sm)
}
/* disable irqs */
- writel(0, sm->regs + SM501_IRQ_MASK);
+ smc501_writel(0, sm->regs + SM501_IRQ_MASK);
- dramctrl = readl(sm->regs + SM501_DRAM_CONTROL);
+ dramctrl = smc501_readl(sm->regs + SM501_DRAM_CONTROL);
mem_avail = sm501_mem_local[(dramctrl >> 13) & 0x7];
dev_info(sm->dev, "SM501 At %p: Version %08lx, %ld Mb, IRQ %d\n",
@@ -1489,7 +1490,7 @@ static int sm501_plat_suspend(struct platform_device *pdev, pm_message_t state)
struct sm501_devdata *sm = platform_get_drvdata(pdev);
sm->in_suspend = 1;
- sm->pm_misc = readl(sm->regs + SM501_MISC_CONTROL);
+ sm->pm_misc = smc501_readl(sm->regs + SM501_MISC_CONTROL);
sm501_dump_regs(sm);
@@ -1513,9 +1514,9 @@ static int sm501_plat_resume(struct platform_device *pdev)
/* check to see if we are in the same state as when suspended */
- if (readl(sm->regs + SM501_MISC_CONTROL) != sm->pm_misc) {
+ if (smc501_readl(sm->regs + SM501_MISC_CONTROL) != sm->pm_misc) {
dev_info(sm->dev, "SM501_MISC_CONTROL changed over sleep\n");
- writel(sm->pm_misc, sm->regs + SM501_MISC_CONTROL);
+ smc501_writel(sm->pm_misc, sm->regs + SM501_MISC_CONTROL);
/* our suspend causes the controller state to change,
* either by something attempting setup, power loss,
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index bcb44a5..5df406c 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -117,7 +117,7 @@ static inline int v_total(struct fb_var_screeninfo *var)
static inline void sm501fb_sync_regs(struct sm501fb_info *info)
{
- readl(info->regs);
+ smc501_readl(info->regs);
}
/* sm501_alloc_mem
@@ -262,7 +262,7 @@ static void sm501fb_setup_gamma(struct sm501fb_info *fbi,
/* set gamma values */
for (offset = 0; offset < 256 * 4; offset += 4) {
- writel(value, fbi->regs + palette + offset);
+ smc501_writel(value, fbi->regs + palette + offset);
value += 0x010101; /* Advance RGB by 1,1,1.*/
}
}
@@ -476,7 +476,8 @@ static int sm501fb_set_par_common(struct fb_info *info,
/* set start of framebuffer to the screen */
- writel(par->screen.sm_addr | SM501_ADDR_FLIP, fbi->regs + head_addr);
+ smc501_writel(par->screen.sm_addr | SM501_ADDR_FLIP,
+ fbi->regs + head_addr);
/* program CRT clock */
@@ -519,7 +520,7 @@ static void sm501fb_set_par_geometry(struct fb_info *info,
reg = info->fix.line_length;
reg |= ((var->xres * var->bits_per_pixel)/8) << 16;
- writel(reg, fbi->regs + (par->head = HEAD_CRT ?
+ smc501_writel(reg, fbi->regs + (par->head = HEAD_CRT ?
SM501_DC_CRT_FB_OFFSET : SM501_DC_PANEL_FB_OFFSET));
/* program horizontal total */
@@ -527,27 +528,27 @@ static void sm501fb_set_par_geometry(struct fb_info *info,
reg = (h_total(var) - 1) << 16;
reg |= (var->xres - 1);
- writel(reg, base + SM501_OFF_DC_H_TOT);
+ smc501_writel(reg, base + SM501_OFF_DC_H_TOT);
/* program horizontal sync */
reg = var->hsync_len << 16;
reg |= var->xres + var->right_margin - 1;
- writel(reg, base + SM501_OFF_DC_H_SYNC);
+ smc501_writel(reg, base + SM501_OFF_DC_H_SYNC);
/* program vertical total */
reg = (v_total(var) - 1) << 16;
reg |= (var->yres - 1);
- writel(reg, base + SM501_OFF_DC_V_TOT);
+ smc501_writel(reg, base + SM501_OFF_DC_V_TOT);
/* program vertical sync */
reg = var->vsync_len << 16;
reg |= var->yres + var->lower_margin - 1;
- writel(reg, base + SM501_OFF_DC_V_SYNC);
+ smc501_writel(reg, base + SM501_OFF_DC_V_SYNC);
}
/* sm501fb_pan_crt
@@ -566,15 +567,15 @@ static int sm501fb_pan_crt(struct fb_var_screeninfo *var,
xoffs = var->xoffset * bytes_pixel;
- reg = readl(fbi->regs + SM501_DC_CRT_CONTROL);
+ reg = smc501_readl(fbi->regs + SM501_DC_CRT_CONTROL);
reg &= ~SM501_DC_CRT_CONTROL_PIXEL_MASK;
reg |= ((xoffs & 15) / bytes_pixel) << 4;
- writel(reg, fbi->regs + SM501_DC_CRT_CONTROL);
+ smc501_writel(reg, fbi->regs + SM501_DC_CRT_CONTROL);
reg = (par->screen.sm_addr + xoffs +
var->yoffset * info->fix.line_length);
- writel(reg | SM501_ADDR_FLIP, fbi->regs + SM501_DC_CRT_FB_ADDR);
+ smc501_writel(reg | SM501_ADDR_FLIP, fbi->regs + SM501_DC_CRT_FB_ADDR);
sm501fb_sync_regs(fbi);
return 0;
@@ -593,10 +594,10 @@ static int sm501fb_pan_pnl(struct fb_var_screeninfo *var,
unsigned long reg;
reg = var->xoffset | (var->xres_virtual << 16);
- writel(reg, fbi->regs + SM501_DC_PANEL_FB_WIDTH);
+ smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_WIDTH);
reg = var->yoffset | (var->yres_virtual << 16);
- writel(reg, fbi->regs + SM501_DC_PANEL_FB_HEIGHT);
+ smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_HEIGHT);
sm501fb_sync_regs(fbi);
return 0;
@@ -622,7 +623,7 @@ static int sm501fb_set_par_crt(struct fb_info *info)
/* enable CRT DAC - note 0 is on!*/
sm501_misc_control(fbi->dev->parent, 0, SM501_MISC_DAC_POWER);
- control = readl(fbi->regs + SM501_DC_CRT_CONTROL);
+ control = smc501_readl(fbi->regs + SM501_DC_CRT_CONTROL);
control &= (SM501_DC_CRT_CONTROL_PIXEL_MASK |
SM501_DC_CRT_CONTROL_GAMMA |
@@ -684,7 +685,7 @@ static int sm501fb_set_par_crt(struct fb_info *info)
out_update:
dev_dbg(fbi->dev, "new control is %08lx\n", control);
- writel(control, fbi->regs + SM501_DC_CRT_CONTROL);
+ smc501_writel(control, fbi->regs + SM501_DC_CRT_CONTROL);
sm501fb_sync_regs(fbi);
return 0;
@@ -696,18 +697,18 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
void __iomem *ctrl_reg = fbi->regs + SM501_DC_PANEL_CONTROL;
struct sm501_platdata_fbsub *pd = fbi->pdata->fb_pnl;
- control = readl(ctrl_reg);
+ control = smc501_readl(ctrl_reg);
if (to && (control & SM501_DC_PANEL_CONTROL_VDD) = 0) {
/* enable panel power */
control |= SM501_DC_PANEL_CONTROL_VDD; /* FPVDDEN */
- writel(control, ctrl_reg);
+ smc501_writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
control |= SM501_DC_PANEL_CONTROL_DATA; /* DATA */
- writel(control, ctrl_reg);
+ smc501_writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
@@ -719,7 +720,7 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
else
control |= SM501_DC_PANEL_CONTROL_BIAS;
- writel(control, ctrl_reg);
+ smc501_writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
}
@@ -730,7 +731,7 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
else
control |= SM501_DC_PANEL_CONTROL_FPEN;
- writel(control, ctrl_reg);
+ smc501_writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
}
@@ -742,7 +743,7 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
else
control &= ~SM501_DC_PANEL_CONTROL_FPEN;
- writel(control, ctrl_reg);
+ smc501_writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
}
@@ -753,18 +754,18 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
else
control &= ~SM501_DC_PANEL_CONTROL_BIAS;
- writel(control, ctrl_reg);
+ smc501_writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
}
control &= ~SM501_DC_PANEL_CONTROL_DATA;
- writel(control, ctrl_reg);
+ smc501_writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
control &= ~SM501_DC_PANEL_CONTROL_VDD;
- writel(control, ctrl_reg);
+ smc501_writel(control, ctrl_reg);
sm501fb_sync_regs(fbi);
mdelay(10);
}
@@ -799,7 +800,7 @@ static int sm501fb_set_par_pnl(struct fb_info *info)
/* update control register */
- control = readl(fbi->regs + SM501_DC_PANEL_CONTROL);
+ control = smc501_readl(fbi->regs + SM501_DC_PANEL_CONTROL);
control &= (SM501_DC_PANEL_CONTROL_GAMMA |
SM501_DC_PANEL_CONTROL_VDD |
SM501_DC_PANEL_CONTROL_DATA |
@@ -833,16 +834,16 @@ static int sm501fb_set_par_pnl(struct fb_info *info)
BUG();
}
- writel(0x0, fbi->regs + SM501_DC_PANEL_PANNING_CONTROL);
+ smc501_writel(0x0, fbi->regs + SM501_DC_PANEL_PANNING_CONTROL);
/* panel plane top left and bottom right location */
- writel(0x00, fbi->regs + SM501_DC_PANEL_TL_LOC);
+ smc501_writel(0x00, fbi->regs + SM501_DC_PANEL_TL_LOC);
reg = var->xres - 1;
reg |= (var->yres - 1) << 16;
- writel(reg, fbi->regs + SM501_DC_PANEL_BR_LOC);
+ smc501_writel(reg, fbi->regs + SM501_DC_PANEL_BR_LOC);
/* program panel control register */
@@ -855,7 +856,7 @@ static int sm501fb_set_par_pnl(struct fb_info *info)
if ((var->sync & FB_SYNC_VERT_HIGH_ACT) = 0)
control |= SM501_DC_PANEL_CONTROL_VSP;
- writel(control, fbi->regs + SM501_DC_PANEL_CONTROL);
+ smc501_writel(control, fbi->regs + SM501_DC_PANEL_CONTROL);
sm501fb_sync_regs(fbi);
/* ensure the panel interface is not tristated at this point */
@@ -924,7 +925,7 @@ static int sm501fb_setcolreg(unsigned regno,
val |= (green >> 8) << 8;
val |= blue >> 8;
- writel(val, base + (regno * 4));
+ smc501_writel(val, base + (regno * 4));
}
break;
@@ -980,7 +981,7 @@ static int sm501fb_blank_crt(int blank_mode, struct fb_info *info)
dev_dbg(fbi->dev, "%s(mode=%d, %p)\n", __func__, blank_mode, info);
- ctrl = readl(fbi->regs + SM501_DC_CRT_CONTROL);
+ ctrl = smc501_readl(fbi->regs + SM501_DC_CRT_CONTROL);
switch (blank_mode) {
case FB_BLANK_POWERDOWN:
@@ -1004,7 +1005,7 @@ static int sm501fb_blank_crt(int blank_mode, struct fb_info *info)
}
- writel(ctrl, fbi->regs + SM501_DC_CRT_CONTROL);
+ smc501_writel(ctrl, fbi->regs + SM501_DC_CRT_CONTROL);
sm501fb_sync_regs(fbi);
return 0;
@@ -1041,12 +1042,14 @@ static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
if (cursor->image.depth > 1)
return -EINVAL;
- hwc_addr = readl(base + SM501_OFF_HWC_ADDR);
+ hwc_addr = smc501_readl(base + SM501_OFF_HWC_ADDR);
if (cursor->enable)
- writel(hwc_addr | SM501_HWC_EN, base + SM501_OFF_HWC_ADDR);
+ smc501_writel(hwc_addr | SM501_HWC_EN,
+ base + SM501_OFF_HWC_ADDR);
else
- writel(hwc_addr & ~SM501_HWC_EN, base + SM501_OFF_HWC_ADDR);
+ smc501_writel(hwc_addr & ~SM501_HWC_EN,
+ base + SM501_OFF_HWC_ADDR);
/* set data */
if (cursor->set & FB_CUR_SETPOS) {
@@ -1060,7 +1063,7 @@ static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
//y += cursor->image.height;
- writel(x | (y << 16), base + SM501_OFF_HWC_LOC);
+ smc501_writel(x | (y << 16), base + SM501_OFF_HWC_LOC);
}
if (cursor->set & FB_CUR_SETCMAP) {
@@ -1080,8 +1083,8 @@ static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
dev_dbg(fbi->dev, "fgcol %08lx, bgcol %08lx\n", fg, bg);
- writel(bg, base + SM501_OFF_HWC_COLOR_1_2);
- writel(fg, base + SM501_OFF_HWC_COLOR_3);
+ smc501_writel(bg, base + SM501_OFF_HWC_COLOR_1_2);
+ smc501_writel(fg, base + SM501_OFF_HWC_COLOR_3);
}
if (cursor->set & FB_CUR_SETSIZE ||
@@ -1102,7 +1105,7 @@ static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
__func__, cursor->image.width, cursor->image.height);
for (op = 0; op < (64*64*2)/8; op+=4)
- writel(0x0, dst + op);
+ smc501_writel(0x0, dst + op);
for (y = 0; y < cursor->image.height; y++) {
for (x = 0; x < cursor->image.width; x++) {
@@ -1141,7 +1144,7 @@ static ssize_t sm501fb_crtsrc_show(struct device *dev,
struct sm501fb_info *info = dev_get_drvdata(dev);
unsigned long ctrl;
- ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+ ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
ctrl &= SM501_DC_CRT_CONTROL_SEL;
return snprintf(buf, PAGE_SIZE, "%s\n", ctrl ? "crt" : "panel");
@@ -1172,7 +1175,7 @@ static ssize_t sm501fb_crtsrc_store(struct device *dev,
dev_info(dev, "setting crt source to head %d\n", head);
- ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+ ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
if (head = HEAD_CRT) {
ctrl |= SM501_DC_CRT_CONTROL_SEL;
@@ -1184,7 +1187,7 @@ static ssize_t sm501fb_crtsrc_store(struct device *dev,
ctrl &= ~SM501_DC_CRT_CONTROL_TE;
}
- writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
+ smc501_writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
sm501fb_sync_regs(info);
return len;
@@ -1205,7 +1208,8 @@ static int sm501fb_show_regs(struct sm501fb_info *info, char *ptr,
unsigned int reg;
for (reg = start; reg < (len + start); reg += 4)
- ptr += sprintf(ptr, "%08x = %08x\n", reg, readl(mem + reg));
+ ptr += sprintf(ptr, "%08x = %08x\n", reg,
+ smc501_readl(mem + reg));
return ptr - buf;
}
@@ -1257,7 +1261,7 @@ static int sm501fb_sync(struct fb_info *info)
/* wait for the 2d engine to be ready */
while ((count > 0) &&
- (readl(fbi->regs + SM501_SYSTEM_CONTROL) &
+ (smc501_readl(fbi->regs + SM501_SYSTEM_CONTROL) &
SM501_SYSCTRL_2D_ENGINE_STATUS) != 0)
count--;
@@ -1312,45 +1316,46 @@ static void sm501fb_copyarea(struct fb_info *info, const struct fb_copyarea *are
return;
/* set the base addresses */
- writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE);
- writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_DESTINATION_BASE);
+ smc501_writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE);
+ smc501_writel(par->screen.sm_addr,
+ fbi->regs2d + SM501_2D_DESTINATION_BASE);
/* set the window width */
- writel((info->var.xres << 16) | info->var.xres,
+ smc501_writel((info->var.xres << 16) | info->var.xres,
fbi->regs2d + SM501_2D_WINDOW_WIDTH);
/* set window stride */
- writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
+ smc501_writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
fbi->regs2d + SM501_2D_PITCH);
/* set data format */
switch (info->var.bits_per_pixel) {
case 8:
- writel(0, fbi->regs2d + SM501_2D_STRETCH);
+ smc501_writel(0, fbi->regs2d + SM501_2D_STRETCH);
break;
case 16:
- writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
+ smc501_writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
break;
case 32:
- writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
+ smc501_writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
break;
}
/* 2d compare mask */
- writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
+ smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
/* 2d mask */
- writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
+ smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
/* source and destination x y */
- writel((sx << 16) | sy, fbi->regs2d + SM501_2D_SOURCE);
- writel((dx << 16) | dy, fbi->regs2d + SM501_2D_DESTINATION);
+ smc501_writel((sx << 16) | sy, fbi->regs2d + SM501_2D_SOURCE);
+ smc501_writel((dx << 16) | dy, fbi->regs2d + SM501_2D_DESTINATION);
/* w/h */
- writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
+ smc501_writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
/* do area move */
- writel(0x800000cc | rtl, fbi->regs2d + SM501_2D_CONTROL);
+ smc501_writel(0x800000cc | rtl, fbi->regs2d + SM501_2D_CONTROL);
}
static void sm501fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
@@ -1372,47 +1377,49 @@ static void sm501fb_fillrect(struct fb_info *info, const struct fb_fillrect *rec
return;
/* set the base addresses */
- writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE);
- writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_DESTINATION_BASE);
+ smc501_writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE);
+ smc501_writel(par->screen.sm_addr,
+ fbi->regs2d + SM501_2D_DESTINATION_BASE);
/* set the window width */
- writel((info->var.xres << 16) | info->var.xres,
+ smc501_writel((info->var.xres << 16) | info->var.xres,
fbi->regs2d + SM501_2D_WINDOW_WIDTH);
/* set window stride */
- writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
+ smc501_writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
fbi->regs2d + SM501_2D_PITCH);
/* set data format */
switch (info->var.bits_per_pixel) {
case 8:
- writel(0, fbi->regs2d + SM501_2D_STRETCH);
+ smc501_writel(0, fbi->regs2d + SM501_2D_STRETCH);
break;
case 16:
- writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
+ smc501_writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
break;
case 32:
- writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
+ smc501_writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
break;
}
/* 2d compare mask */
- writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
+ smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
/* 2d mask */
- writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
+ smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
/* colour */
- writel(rect->color, fbi->regs2d + SM501_2D_FOREGROUND);
+ smc501_writel(rect->color, fbi->regs2d + SM501_2D_FOREGROUND);
/* x y */
- writel((rect->dx << 16) | rect->dy, fbi->regs2d + SM501_2D_DESTINATION);
+ smc501_writel((rect->dx << 16) | rect->dy,
+ fbi->regs2d + SM501_2D_DESTINATION);
/* w/h */
- writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
+ smc501_writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
/* do rectangle fill */
- writel(0x800100cc, fbi->regs2d + SM501_2D_CONTROL);
+ smc501_writel(0x800100cc, fbi->regs2d + SM501_2D_CONTROL);
}
@@ -1470,11 +1477,12 @@ static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base)
/* initialise the colour registers */
- writel(par->cursor.sm_addr, par->cursor_regs + SM501_OFF_HWC_ADDR);
+ smc501_writel(par->cursor.sm_addr,
+ par->cursor_regs + SM501_OFF_HWC_ADDR);
- writel(0x00, par->cursor_regs + SM501_OFF_HWC_LOC);
- writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_1_2);
- writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_3);
+ smc501_writel(0x00, par->cursor_regs + SM501_OFF_HWC_LOC);
+ smc501_writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_1_2);
+ smc501_writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_3);
sm501fb_sync_regs(info);
return 0;
@@ -1581,7 +1589,7 @@ static int sm501fb_start(struct sm501fb_info *info,
/* clear palette ram - undefined at power on */
for (k = 0; k < (256 * 3); k++)
- writel(0, info->regs + SM501_DC_PANEL_PALETTE + (k * 4));
+ smc501_writel(0, info->regs + SM501_DC_PANEL_PALETTE + (k * 4));
/* enable display controller */
sm501_unit_power(dev->parent, SM501_GATE_DISPLAY, 1);
@@ -1649,20 +1657,20 @@ static int sm501fb_init_fb(struct fb_info *fb,
switch (head) {
case HEAD_CRT:
pd = info->pdata->fb_crt;
- ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+ ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
enable = (ctrl & SM501_DC_CRT_CONTROL_ENABLE) ? 1 : 0;
/* ensure we set the correct source register */
if (info->pdata->fb_route != SM501_FB_CRT_PANEL) {
ctrl |= SM501_DC_CRT_CONTROL_SEL;
- writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
+ smc501_writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
}
break;
case HEAD_PANEL:
pd = info->pdata->fb_pnl;
- ctrl = readl(info->regs + SM501_DC_PANEL_CONTROL);
+ ctrl = smc501_readl(info->regs + SM501_DC_PANEL_CONTROL);
enable = (ctrl & SM501_DC_PANEL_CONTROL_EN) ? 1 : 0;
break;
@@ -1680,7 +1688,7 @@ static int sm501fb_init_fb(struct fb_info *fb,
if (head = HEAD_CRT && info->pdata->fb_route = SM501_FB_CRT_PANEL) {
ctrl &= ~SM501_DC_CRT_CONTROL_SEL;
- writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
+ smc501_writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
enable = 0;
}
@@ -2085,7 +2093,7 @@ static int sm501fb_suspend(struct platform_device *pdev, pm_message_t state)
struct sm501fb_info *info = platform_get_drvdata(pdev);
/* store crt control to resume with */
- info->pm_crt_ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+ info->pm_crt_ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
sm501fb_suspend_fb(info, HEAD_CRT);
sm501fb_suspend_fb(info, HEAD_PANEL);
@@ -2109,10 +2117,10 @@ static int sm501fb_resume(struct platform_device *pdev)
/* restore the items we want to be saved for crt control */
- crt_ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+ crt_ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
crt_ctrl &= ~SM501_CRT_CTRL_SAVE;
crt_ctrl |= info->pm_crt_ctrl & SM501_CRT_CTRL_SAVE;
- writel(crt_ctrl, info->regs + SM501_DC_CRT_CONTROL);
+ smc501_writel(crt_ctrl, info->regs + SM501_DC_CRT_CONTROL);
sm501fb_resume_fb(info, HEAD_CRT);
sm501fb_resume_fb(info, HEAD_PANEL);
diff --git a/include/linux/sm501.h b/include/linux/sm501.h
index 214f932..02fde50 100644
--- a/include/linux/sm501.h
+++ b/include/linux/sm501.h
@@ -172,3 +172,11 @@ struct sm501_platdata {
struct sm501_platdata_gpio_i2c *gpio_i2c;
unsigned int gpio_i2c_nr;
};
+
+#if defined(CONFIG_PPC32)
+#define smc501_readl(addr) ioread32be((addr))
+#define smc501_writel(val, addr) iowrite32be((val), (addr))
+#else
+#define smc501_readl(addr) readl(addr)
+#define smc501_writel(val, addr) writel(val, addr)
+#endif
--
1.7.4
^ permalink raw reply related
* [PATCH v1 1/6] powerpc, 5200: add support for charon board
From: Heiko Schocher @ 2011-03-22 8:27 UTC (permalink / raw)
To: linuxppc-dev
Cc: Heiko Schocher, Wolfram Sang, Grant Likely,
Benjamin Herrenschmidt, linux-fbdev, devicetree-discuss,
Ben Dooks, Vincent Sanders, Samuel Ortiz, linux-kernel,
Randy Dunlap, Wolfgang Denk, Paul Mundt
In-Reply-To: <1300782452-528-1-git-send-email-hs@denx.de>
Signed-off-by: Heiko Schocher <hs@denx.de>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
cc: Wolfram Sang <w.sang@pengutronix.de>
cc: Grant Likely <grant.likely@secretlab.ca>
cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
cc: linux-fbdev@vger.kernel.org
cc: devicetree-discuss@ozlabs.org
cc: Ben Dooks <ben@simtec.co.uk>
cc: Vincent Sanders <vince@simtec.co.uk>
cc: Samuel Ortiz <sameo@linux.intel.com>
cc: linux-kernel@vger.kernel.org
cc: Randy Dunlap <rdunlap@xenotime.net>
cc: Wolfgang Denk <wd@denx.de>
cc: Paul Mundt <lethal@linux-sh.org>
---
- changes since v1:
add comments from Wolfram Sang
- no defconfig file
- comment corrected in DTS
- boardlist sorted alphabetically
- commit log without boardinfo
- changes for v6:
- rebased against current head
- repost complete patchserie
- added Acked-by from Benjamin Herrenschmidt
arch/powerpc/boot/dts/charon.dts | 226 ++++++++++++++++++++++++++
arch/powerpc/platforms/52xx/mpc5200_simple.c | 1 +
2 files changed, 227 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/boot/dts/charon.dts
diff --git a/arch/powerpc/boot/dts/charon.dts b/arch/powerpc/boot/dts/charon.dts
new file mode 100644
index 0000000..9776889
--- /dev/null
+++ b/arch/powerpc/boot/dts/charon.dts
@@ -0,0 +1,226 @@
+/*
+ * charon board Device Tree Source
+ *
+ * Copyright (C) 2007 Semihalf
+ * Marian Balakowicz <m8@semihalf.com>
+ *
+ * Copyright (C) 2010 DENX Software Engineering GmbH
+ * Heiko Schocher <hs@denx.de>
+ *
+ * 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.
+ */
+
+/dts-v1/;
+
+/ {
+ model = "anon,charon";
+ compatible = "anon,charon";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&mpc5200_pic>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ PowerPC,5200@0 {
+ device_type = "cpu";
+ reg = <0>;
+ d-cache-line-size = <32>;
+ i-cache-line-size = <32>;
+ d-cache-size = <0x4000>; // L1, 16K
+ i-cache-size = <0x4000>; // L1, 16K
+ timebase-frequency = <0>; // from bootloader
+ bus-frequency = <0>; // from bootloader
+ clock-frequency = <0>; // from bootloader
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x00000000 0x08000000>; // 128MB
+ };
+
+ soc5200@f0000000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc5200-immr";
+ ranges = <0 0xf0000000 0x0000c000>;
+ reg = <0xf0000000 0x00000100>;
+ bus-frequency = <0>; // from bootloader
+ system-frequency = <0>; // from bootloader
+
+ cdm@200 {
+ compatible = "fsl,mpc5200-cdm";
+ reg = <0x200 0x38>;
+ };
+
+ mpc5200_pic: interrupt-controller@500 {
+ // 5200 interrupts are encoded into two levels;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ compatible = "fsl,mpc5200-pic";
+ reg = <0x500 0x80>;
+ };
+
+ timer@600 { // General Purpose Timer
+ compatible = "fsl,mpc5200-gpt";
+ reg = <0x600 0x10>;
+ interrupts = <1 9 0>;
+ fsl,has-wdt;
+ };
+
+ can@900 {
+ compatible = "fsl,mpc5200-mscan";
+ interrupts = <2 17 0>;
+ reg = <0x900 0x80>;
+ };
+
+ can@980 {
+ compatible = "fsl,mpc5200-mscan";
+ interrupts = <2 18 0>;
+ reg = <0x980 0x80>;
+ };
+
+ gpio_simple: gpio@b00 {
+ compatible = "fsl,mpc5200-gpio";
+ reg = <0xb00 0x40>;
+ interrupts = <1 7 0>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ usb@1000 {
+ compatible = "fsl,mpc5200-ohci","ohci-be";
+ reg = <0x1000 0xff>;
+ interrupts = <2 6 0>;
+ };
+
+ dma-controller@1200 {
+ device_type = "dma-controller";
+ compatible = "fsl,mpc5200-bestcomm";
+ reg = <0x1200 0x80>;
+ interrupts = <3 0 0 3 1 0 3 2 0 3 3 0
+ 3 4 0 3 5 0 3 6 0 3 7 0
+ 3 8 0 3 9 0 3 10 0 3 11 0
+ 3 12 0 3 13 0 3 14 0 3 15 0>;
+ };
+
+ xlb@1f00 {
+ compatible = "fsl,mpc5200-xlb";
+ reg = <0x1f00 0x100>;
+ };
+
+ serial@2000 { // PSC1
+ compatible = "fsl,mpc5200-psc-uart";
+ reg = <0x2000 0x100>;
+ interrupts = <2 1 0>;
+ };
+
+ serial@2400 { // PSC3
+ compatible = "fsl,mpc5200-psc-uart";
+ reg = <0x2400 0x100>;
+ interrupts = <2 3 0>;
+ };
+
+ ethernet@3000 {
+ compatible = "fsl,mpc5200-fec";
+ reg = <0x3000 0x400>;
+ local-mac-address = [ 00 00 00 00 00 00 ];
+ interrupts = <2 5 0>;
+ fixed-link = <1 1 100 0 0>;
+ };
+
+ mdio@3000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,mpc5200-mdio";
+ reg = <0x3000 0x400>; // fec range, since we need to setup fec interrupts
+ interrupts = <2 5 0>; // these are for "mii command finished", not link changes & co.
+ };
+
+ ata@3a00 {
+ compatible = "fsl,mpc5200-ata";
+ reg = <0x3a00 0x100>;
+ interrupts = <2 7 0>;
+ };
+
+ i2c@3d00 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,mpc5200-i2c","fsl-i2c";
+ reg = <0x3d00 0x40>;
+ interrupts = <2 15 0>;
+ };
+
+
+ i2c@3d40 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,mpc5200-i2c","fsl-i2c";
+ reg = <0x3d40 0x40>;
+ interrupts = <2 16 0>;
+
+ dtt@28 {
+ compatible = "national,lm80";
+ reg = <0x28>;
+ };
+
+ rtc@68 {
+ compatible = "dallas,ds1374";
+ reg = <0x68>;
+ };
+ };
+
+ sram@8000 {
+ compatible = "fsl,mpc5200-sram";
+ reg = <0x8000 0x4000>;
+ };
+ };
+
+ localbus {
+ compatible = "fsl,mpc5200-lpb","simple-bus";
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ranges = < 0 0 0xfc000000 0x02000000
+ 3 0 0xe8000000 0x00080000>;
+
+ flash@0,0 {
+ compatible = "cfi-flash";
+ reg = <0 0 0x02000000>;
+ bank-width = <4>;
+ device-width = <2>;
+ #size-cells = <1>;
+ #address-cells = <1>;
+ };
+
+ mram0@3,0 {
+ compatible = "mtd-ram";
+ reg = <3 0x00000 0x80000>;
+ bank-width = <1>;
+ };
+ };
+
+ pci@f0000d00 {
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ device_type = "pci";
+ compatible = "fsl,mpc5200-pci";
+ reg = <0xf0000d00 0x100>;
+ interrupt-map-mask = <0xf800 0 0 7>;
+ interrupt-map = <0xc000 0 0 1 &mpc5200_pic 0 0 3
+ 0xc000 0 0 2 &mpc5200_pic 0 0 3
+ 0xc000 0 0 3 &mpc5200_pic 0 0 3
+ 0xc000 0 0 4 &mpc5200_pic 0 0 3>;
+ clock-frequency = <0>; // From boot loader
+ interrupts = <2 8 0 2 9 0 2 10 0>;
+ bus-range = <0 0>;
+ ranges = <0x42000000 0 0x80000000 0x80000000 0 0x10000000
+ 0x02000000 0 0x90000000 0x90000000 0 0x10000000
+ 0x01000000 0 0x00000000 0xa0000000 0 0x01000000>;
+ };
+};
diff --git a/arch/powerpc/platforms/52xx/mpc5200_simple.c b/arch/powerpc/platforms/52xx/mpc5200_simple.c
index e36d6e2..846b789 100644
--- a/arch/powerpc/platforms/52xx/mpc5200_simple.c
+++ b/arch/powerpc/platforms/52xx/mpc5200_simple.c
@@ -50,6 +50,7 @@ static void __init mpc5200_simple_setup_arch(void)
/* list of the supported boards */
static const char *board[] __initdata = {
+ "anon,charon",
"intercontrol,digsy-mtc",
"manroland,mucmc52",
"manroland,uc101",
--
1.7.4
^ permalink raw reply related
* [PATCH v6 0/6] powerpc, 52xx: add charon board support
From: Heiko Schocher @ 2011-03-22 8:27 UTC (permalink / raw)
To: linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ
Cc: Ben Dooks, linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, Samuel Ortiz,
Vincent Sanders, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
Randy Dunlap, Paul Mundt, Heiko Schocher, Wolfgang Denk
In-Reply-To: <1291451028-22532-1-git-send-email-hs-ynQEQJNshbs@public.gmane.org>
cc: Wolfram Sang <w.sang@pengutronix.de>
cc: Grant Likely <grant.likely@secretlab.ca>
cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
cc: linux-fbdev@vger.kernel.org
cc: devicetree-discuss@ozlabs.org
cc: Ben Dooks <ben@simtec.co.uk>
cc: Vincent Sanders <vince@simtec.co.uk>
cc: Samuel Ortiz <sameo@linux.intel.com>
cc: linux-kernel@vger.kernel.org
cc: Randy Dunlap <rdunlap@xenotime.net>
cc: Wolfgang Denk <wd@denx.de>
cc: Paul Mundt <lethal@linux-sh.org>
changes since v5:
- repost complete patchseries, as Paul Mundt suggested
- rebased against current head
- add Acked-by from Samuel Ortiz (MFD parts)
http://www.spinics.net/lists/linux-fbdev/msg02550.html
http://linux.derkeiler.com/Mailing-Lists/Kernel/2011-01/msg11798.html
and Benjamin Herrenschmidt (DTS parts)
http://lists.ozlabs.org/pipermail/linuxppc-dev/2011-February/088279.html
- removed patch
"powerpc, mpc5200: update mpc5200_defconfig to fit for charon board."
therefore added
"powerpc, tqm5200: update tqm5200_defconfig to fit for charon board."
Paul: before adding this patchseries, this patch should get
an Acked-by from a powerpc maintainer.
checkpatch says:
total: 0 errors, 0 warnings, 233 lines checked
20110322/0001-powerpc-5200-add-support-for-charon-board.patch has no obvious style problems and is ready for submission.
total: 0 errors, 0 warnings, 841 lines checked
20110322/0002-video-sm501-add-I-O-functions-for-use-on-powerpc.patch has no obvious style problems and is ready for submission.
total: 0 errors, 0 warnings, 109 lines checked
20110322/0003-video-sm501-add-edid-and-commandline-support.patch has no obvious style problems and is ready for submission.
total: 0 errors, 0 warnings, 106 lines checked
20110322/0004-video-sm501-add-OF-binding-to-support-SM501.patch has no obvious style problems and is ready for submission.
total: 0 errors, 0 warnings, 22 lines checked
20110322/0005-powerpc-video-add-SM501-support-for-charon-board.patch has no obvious style problems and is ready for submission.
total: 0 errors, 0 warnings, 82 lines checked
20110322/0006-powerpc-tqm5200-update-tqm5200_defconfig-to-fit-for-.patch has no obvious style problems and is ready for submission.
Heiko Schocher (6):
powerpc, 5200: add support for charon board
video, sm501: add I/O functions for use on powerpc
video, sm501: add edid and commandline support
video, sm501: add OF binding to support SM501
powerpc, video: add SM501 support for charon board.
powerpc, tqm5200: update tqm5200_defconfig to fit for charon board.
Documentation/fb/sm501.txt | 10 +
Documentation/powerpc/dts-bindings/sm501.txt | 34 ++++
arch/powerpc/boot/dts/charon.dts | 236 ++++++++++++++++++++++
arch/powerpc/configs/52xx/tqm5200_defconfig | 20 ++-
arch/powerpc/platforms/52xx/mpc5200_simple.c | 1 +
drivers/mfd/sm501.c | 133 +++++++------
drivers/video/sm501fb.c | 272 +++++++++++++++++---------
include/linux/sm501.h | 8 +
8 files changed, 555 insertions(+), 159 deletions(-)
create mode 100644 Documentation/fb/sm501.txt
create mode 100644 Documentation/powerpc/dts-bindings/sm501.txt
create mode 100644 arch/powerpc/boot/dts/charon.dts
--
1.7.4
^ permalink raw reply
* Re: [PATCH 3/4 v5] video, sm501: add OF binding to support SM501
From: Heiko Schocher @ 2011-03-22 8:25 UTC (permalink / raw)
To: Paul Mundt
Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
devicetree-discuss-mnsaURCQ41sdnm+yROfE0A, Samuel Ortiz,
Vincent Sanders, linux-kernel-u79uwXL29TY76Z2rM5mHXA, Ben Dooks,
Randy Dunlap, linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, Wolfgang Denk
In-Reply-To: <20110322082047.GG25925-M7jkjyW5wf5g9hUCZPvPmw@public.gmane.org>
Hello Paul,
Paul Mundt wrote:
> On Thu, Mar 17, 2011 at 07:12:56AM +0100, Heiko Schocher wrote:
>> Paul Mundt schrieb:
>>> On Tue, Mar 15, 2011 at 08:26:40AM +0100, Heiko Schocher wrote:
>>>>> 0003-video-sm501-add-OF-binding-to-support-SM501.patch has no obvious style problems and is ready for submission.
>>>>>
>>>>> Documentation/powerpc/dts-bindings/sm501.txt | 34 +++++++++++++++++++++
>>>>> drivers/mfd/sm501.c | 9 +++++-
>>>>> drivers/video/sm501fb.c | 42 ++++++++++++++++++++++++--
>>>>> 3 files changed, 81 insertions(+), 4 deletions(-)
>>>>> create mode 100644 Documentation/powerpc/dts-bindings/sm501.txt
>>>> This patchset is pending know for a while. I got Acked by from
>>>>
>>>> Samuel Ortiz for the mfd part, see here:
>>>>
>>>> http://www.spinics.net/lists/linux-fbdev/msg02550.html
>>>> http://linux.derkeiler.com/Mailing-Lists/Kernel/2011-01/msg11798.html
>>>>
>>>> and for the DTS part from Benjamin Herrenschmidt:
>>>>
>>>> http://lists.ozlabs.org/pipermail/linuxppc-dev/2011-February/088279.html
>>>>
>>>> Are there some more issues?
>>>>
>>> Not that I remember off the top of my head, but I think they've been lost
>>> in my backlog. Could you re-send the current series with the appropriate
>>> acked-bys? If there's nothing else obvious outstanding I'll roll them in.
>> Ok, I resend them (I also rebase them to current tree, ok?)
>>
> Ok, I've dug them up on l-k in the meantime and applied 1-3. 4/4 doesn't
> apply due to a missing dts file, but I assume you're aware of that and
> will take care of it separately. Let me know if I've overlooked anything,
> and sorry for the delay!
No problem!
Just working on this patchset (rebase and check if it boots/works) ... will
post the update (with all patches again) in some minutes, so please wait
for it.
Thanks!
bye,
Heiko
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
^ permalink raw reply
* Re: [PATCH 3/4 v5] video, sm501: add OF binding to support SM501
From: Paul Mundt @ 2011-03-22 8:20 UTC (permalink / raw)
To: Heiko Schocher
Cc: linux-fbdev, devicetree-discuss, Samuel Ortiz, Vincent Sanders,
linux-kernel, Ben Dooks, Randy Dunlap, linuxppc-dev,
Wolfgang Denk
In-Reply-To: <4D81A668.8060500@denx.de>
On Thu, Mar 17, 2011 at 07:12:56AM +0100, Heiko Schocher wrote:
> Paul Mundt schrieb:
> > On Tue, Mar 15, 2011 at 08:26:40AM +0100, Heiko Schocher wrote:
> >>> 0003-video-sm501-add-OF-binding-to-support-SM501.patch has no obvious style problems and is ready for submission.
> >>>
> >>> Documentation/powerpc/dts-bindings/sm501.txt | 34 +++++++++++++++++++++
> >>> drivers/mfd/sm501.c | 9 +++++-
> >>> drivers/video/sm501fb.c | 42 ++++++++++++++++++++++++--
> >>> 3 files changed, 81 insertions(+), 4 deletions(-)
> >>> create mode 100644 Documentation/powerpc/dts-bindings/sm501.txt
> >> This patchset is pending know for a while. I got Acked by from
> >>
> >> Samuel Ortiz for the mfd part, see here:
> >>
> >> http://www.spinics.net/lists/linux-fbdev/msg02550.html
> >> http://linux.derkeiler.com/Mailing-Lists/Kernel/2011-01/msg11798.html
> >>
> >> and for the DTS part from Benjamin Herrenschmidt:
> >>
> >> http://lists.ozlabs.org/pipermail/linuxppc-dev/2011-February/088279.html
> >>
> >> Are there some more issues?
> >>
> > Not that I remember off the top of my head, but I think they've been lost
> > in my backlog. Could you re-send the current series with the appropriate
> > acked-bys? If there's nothing else obvious outstanding I'll roll them in.
>
> Ok, I resend them (I also rebase them to current tree, ok?)
>
Ok, I've dug them up on l-k in the meantime and applied 1-3. 4/4 doesn't
apply due to a missing dts file, but I assume you're aware of that and
will take care of it separately. Let me know if I've overlooked anything,
and sorry for the delay!
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox