blob: 9083701df6fc760a9908906700c66f3edecd43f6 [file] [log] [blame]
\ See license at end of file
purpose: MMP3 HDMI driver
new-device
" hdmi" device-name
" mrvl,pxa688-hdmi" +compatible
0 0 encode-bytes
hdmi-hp-det-gpio# 0 encode-gpio
" gpios" property
" /hdmi-i2c" encode-phandle " ddc-i2c-bus" property
" HDMI" model
: +i encode-int encode+ ;
h# 60010005 " clock-divider-regval" integer-property
decimal
0 0 encode-bytes
\ xres, yres, refresh, clockhz, left, right, top, bottom, hsync, vsync, flags, widthmm, heightmm
1280 +i 720 +i 60 +i 74,250,000 +i 110 +i 220 +i 5 +i 20 +i 40 +i 5 +i 1 +i 0 +i 0 +i
hex
" linux,timing-modes" property
" 1280x720@60" " linux,mode-names" string-property
finish-device
: hdmi-present? ( -- flag ) hdmi-hp-det-gpio# gpio-pin@ 0= ;
: +hdmi h# 20bc00 + ;
: hdmi! +hdmi io! ;
: hdmi@ +hdmi io@ ;
: hdmi-i! ( b reg# -- ) swap 0 hdmi! h# 8000.0000 or 4 hdmi! ;
: hdmi-i@ ( reg# -- b ) h# 4000.0000 or 4 hdmi! 0 hdmi@ ;
: phy-cfg0@ ( -- n ) h# 08 hdmi@ ; : phy-cfg0! ( n -- ) h# 08 hdmi! ;
: phy-cfg1@ ( -- n ) h# 0c hdmi@ ; : phy-cfg1! ( n -- ) h# 0c hdmi! ;
: phy-cfg2@ ( -- n ) h# 10 hdmi@ ; : phy-cfg2! ( n -- ) h# 10 hdmi! ;
: phy-cfg3@ ( -- n ) h# 14 hdmi@ ; : phy-cfg3! ( n -- ) h# 14 hdmi! ;
: audio-cfg@ ( -- n ) h# 18 hdmi@ ; : audio-cfg! ( n -- ) h# 18 hdmi! ;
: clock-cfg@ ( -- n ) h# 1c hdmi@ ; : clock-cfg! ( n -- ) h# 1c hdmi! ;
: pll-cfg0@ ( -- n ) h# 20 hdmi@ ; : pll-cfg0! ( n -- ) h# 20 hdmi! ;
: pll-cfg1@ ( -- n ) h# 24 hdmi@ ; : pll-cfg1! ( n -- ) h# 24 hdmi! ;
: pll-cfg2@ ( -- n ) h# 28 hdmi@ ; : pll-cfg2! ( n -- ) h# 28 hdmi! ;
: pll-cfg3@ ( -- n ) h# 2c hdmi@ ; : pll-cfg3! ( n -- ) h# 2c hdmi! ;
: -bits ( n value bit# -- n' ) lshift invert and ;
: +bits ( n value bit# -- n' ) lshift or ;
[ifdef] debug-words
h# f090099 value pll3-ctrl1
h# 9b value pll3-fbdiv
h# 3 value pll3-refdiv
: pll3-on
h# 20000000 h# 58 mpmu-clr \ Reset PLL3 reset
h# 100 h# 50 mpmu-clr \ Ensure PLL3 off
1 h# 60 mpmu-set \ set SEL_VCO_CLK_SE in PMUM_PLL3_CTRL2
0 pll3-refdiv d# 19 +bits pll3-fbdiv d# 10 +bits 1 d# 9 +bits h# 50 mpmu!
pll3-ctrl1 h# 58 mpmu!
h# 100 h# 50 mpmu-set \ Power up PLL3
d# 50 us
h# 20000000 h# 58 mpmu-set \ Release PLL3 reset
;
create pll-table-mmp2
decimal
\ f div offset fb ref kvco
25 , 4 , h# 4ec5 , 38 , 16 , h# c ,
27 , 4 , h# 35cb , 41 , 16 , h# b ,
54 , 2 , h# 35cb , 41 , 16 , h# b ,
74 , 2 , h# 84b , 57 , 16 , h# 3 ,
108 , 1 , h# 35cb , 41 , 16 , h# b ,
148 , 1 , h# 84b , 57 , 16 , h# 3 ,
-1 ,
hex
[then]
create pll-table
decimal
\ 0 1 2 3 4 5
\ f post offset fb ref kvco
25 , 3 , h# 1171d , 39 , 0 , h# 2 ,
27 , 3 , h# 12710 , 42 , 0 , h# 2 ,
54 , 2 , h# 12710 , 42 , 0 , h# 2 ,
74 , 2 , h# 007e8 , 57 , 0 , h# 4 ,
108 , 1 , h# 1247d , 42 , 0 , h# 2 ,
148 , 1 , h# 007e8 , 57 , 0 , h# 4 ,
-1 ,
hex
: find-pll ( freq -- adr )
pll-table begin dup @ -1 <> while ( freq adr )
2dup @ = if nip exit then ( freq adr )
6 na+ ( freq adr' )
repeat ( freq adr )
-6 na+
;
1 value vpll-calclk-div
1 value vddm
9 value vddl
9 value icp
2 value vreg-ivref
0 value reset-offset
1 value clk-det-en
5 value intpi
0 value reset-intp-ext
1 value pll-mode
2 value vth-vpll-ca
: pll-cfg ( freq -- )
find-pll >r ( table-adr )
pll-cfg3@ 3 invert and pll-cfg3! \ Power off and reset
0
intpi d# 27 +bits
clk-det-en d# 26 +bits
r@ 5 na+ @ d# 20 +bits \ KVCO
vreg-ivref d# 17 +bits
r@ 1 na+ @ d# 14 +bits \ POSTDIV
icp d# 10 +bits
vddl d# 6 +bits
vddm d# 4 +bits
vpll-calclk-div d# 1 +bits
1 d# 0 +bits \ "Chicken bit" to enable PHY register access
pll-cfg0!
0
vth-vpll-ca d# 29 +bits
1 d# 24 +bits \ EN_PANEL
1 d# 23 +bits \ EN_HDMI
r@ 2 na+ @ d# 4 +bits \ FREQ_OFFSET_INNER
pll-mode d# 3 +bits \ MODE
dup pll-cfg1! ( n )
1 d# 22 +bits \ load FREQ_OFFSET_INNER
pll-cfg1! ( )
0 \ FREQ_OFFSET_ADJ
pll-cfg2!
pll-cfg3@
h# fffc invert and \ Clear FBDIV and REFDIV fields
r@ 3 na+ @ d# 7 +bits
r@ 4 na+ @ d# 2 +bits
dup pll-cfg3! \ Set divisors
1 or dup pll-cfg3! 1 ms \ Power up
2 or pll-cfg3! \ Release reset
d# 100 0 do
pll-cfg3@ h# 400000 and ?leave
1 ms
i 9 = if ." HDMI PLL failed to lock" cr then
loop
r> drop
;
: send-packet ( adr len packet# -- )
>r ( adr len r: packet# )
r@ d# 32 * h# 60 + ( adr len index )
\ Clear trailing bytes
over d# 31 swap ?do ( adr len index )
0 i hdmi-i! ( adr len index )
loop
0 swap 2swap ( sum index adr len )
0 ?do ( sum index adr )
2dup i + c@ ( sum index adr index byte )
tuck swap c! ( sum index adr byte )
3 roll + -rot ( sum' index adr )
loop ( sum index adr )
drop ( sum index )
swap negate h# ff and ( index sum' )
over 3 + hdmi-i! ( index )
\ I'm not sure what this is for; one of the drivers did it
1 over d# 31 + hdmi-i! ( index )
drop ( )
1 r> lshift dup h# 5f hdmi-i! h# 5e hdmi-i! \ HDTX_HOST_PKT_CTRL1/0
;
create avi-packet
h# 82 c, h# 2 c, h# 0d c, 0 c, \ 0-3: header
h# 10 c, \ 4: 10 is active format, validates bits 3:0 of next byte
h# a8 c, \ 5: 80 is ITU709 colors, 20 is 16:9, 8 is same aspect ratio
h# 00 c, \ 6: 80 bit means computer display ...
h# 00 c, \ 7: panel type
0 c, \ 8: pixel repetition factor
\ The rest would be top, bottom, left, right bars
here avi-packet - constant /avi-packet
\ The columns up to "Code" are from CEA-861-D (the DVI spec)
\ The remaining columns (sync parameters) are from Marvell bringup code - lcd0_tv.c
create hdmi-resolutions
decimal
\ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
\ Hact Vact Refr Htot Hblnk Vtotal Vblnk PxMHz Code Hsync Hfp Hbp Vsync Vfp Vbp
640 , 480 , 60 , 800 , 160 , 525 , 45 , 25 , 1 , 96 , 48 , 16 , 2 , 33 , 10 ,
720 , 480 , 60 , 858 , 138 , 525 , 45 , 27 , 3 , 62 , 60 , 16 , 6 , 30 , 9 ,
1280 , 720 , 60 , 1650 , 370 , 750 , 30 , 74 , 4 , 40 , 220 , 110 , 5 , 20 , 5 ,
1440 , 240 , 60 , 1716 , 276 , 262 , 22 , 27 , 9 , 124 , 114 , 38 , 3 , 15 , 4 ,
\ 2880 , 240 , 60 , 3432 , 552 , 262 , 22 , 54 , 13 , ??? \ Sync values unknown ...
\ 1440 , 480 , 60 , 1716 , 276 , 525 , 45 , 54 , 15 , ???
1920 , 1080 , 60 , 2200 , 280 , 1125 , 45 , 148 , 16 , 44 , 148 , 88 , 5 , 36 , 4 ,
720 , 576 , 50 , 864 , 144 , 625 , 49 , 27 , 18 , 64 , 68 , 12 , 5 , 39 , 5 ,
1440 , 288 , 50 , 1728 , 288 , 312 , 24 , 27 , 24 , 126 , 138 , 24 , 3 , 18 , 3 ,
\ 2880 , 288 , 50 , 3456 , 576 , 312 , 24 , 54 , 28 , ???
\ 2880 , 480 , 60 , 3432 , 552 , 525 , 45 , 108 , 36 , ???
\ 2880 , 576 , 50 , 3456 , 576 , 625 , 49 , 108 , 38 , ???
-1 ,
hex
0 value res-adr
: res@ ( index -- value ) res-adr swap na+ @ ;
: find-resolution ( h v -- error? )
hdmi-resolutions begin ( h v adr )
dup @ -1 <> ( h v adr flag )
while ( h v adr )
3dup 2@ swap d= if ( h v adr )
to res-adr 2drop ( )
false exit ( -- adr false )
then ( h v adr )
d# 15 na+ ( h v adr' )
repeat ( h v adr )
3drop true
;
: set-hdmi-clock-cfg ( -- )
\ 3 \ The docs say to write 0 to bits 0:3 but the code writes 3
\ On MMP2 this is the the FIFO read and write timing
0
1 4 +bits \ HDMI_ENABLE
6 5 +bits \ MCLK_DIV
5 9 +bits \ TCLK_DIV
5 d# 13 +bits \ PRCLK_DIV
clock-cfg!
;
: hdmi-set-detection ( on/off -- )
h# 14 hdmi@ h# 400 ( on/off value bitmask )
rot if or else invert and then ( value' )
h# 14 hdmi!
;
: select-phy ( -- ) pll-cfg0@ 1 or pll-cfg0! ; \ alias phy select-phy
: select-3d ( -- ) pll-cfg0@ 1 invert and pll-cfg0! ;
\ Tune these for best eye diagram
6 value damp 2 value eamp 0 value cp
0 value ajd 1 value svtx 8 value idrv
: setup-phy ( freq -- )
d# 148 = if 9 else 8 then to idrv
select-phy
damp o# 1111 *
eamp o# 11110000 * or
cp h# 55000000 * or
phy-cfg0!
ajd h# f0000000 *
svtx o# 1111 * d# 16 +bits
idrv h# 1111 * 0 +bits
phy-cfg1!
;
: setup-fifo ( -- )
1 h# 3a hdmi-i! \ HDMI, not DCI, Mode. No pixel repetition
1 h# 48 hdmi-i! \ DC_FIFO_WR_PTR \ Alt value: 0
h# 1a h# 49 hdmi-i! \ DC_FIFO_RD_PTR \ Alt value: 1f
1 h# 47 hdmi-i! \ DC_FIFO_SFT_RST
0 h# 47 hdmi-i! \ DC_FIFO_SFT_RST
8 h# 131 hdmi-i! \ PHY_FIFO_PTRS \ Alt value: 80
1 h# 130 hdmi-i! \ PHY_FIFO_SOFT_RST
0 h# 130 hdmi-i! \ PHY_FIFO_SOFT_RST
0 h# 39 hdmi-i! \ VIDEO_CTRL
h# 40 h# 39 hdmi-i! \ VIDEO_CTRL (set INT_FRM_SEL) \ Alt value: 58
;
: hdmi-video-cfg ( -- )
true hdmi-set-detection
7 res@ pll-cfg
set-hdmi-clock-cfg
0 phy-cfg2! \ Unreset TX
h# 0001.0000 phy-cfg2! \ RESET_TX
h# 10 phy-cfg2! \ Termination
8 res@ avi-packet 7 + c!
avi-packet /avi-packet 1 send-packet
h# e0 h# 58 hdmi-i! \ HDTX_TDATA3_0
h# 83 h# 59 hdmi-i! \ HDTX_TDATA3_1
h# 0f h# 5a hdmi-i! \ HDTX_TDATA3_2
7 res@ setup-phy
setup-fifo
;
: init-tv-clock ( -- )
h# 4c pmua@ dup h# 10 and 0= if ( val )
\ h# f8fc0 invert and \ Clear prescaler and divisor fields
\ h# d0280 or \ DSI PHY Prescaler to default value 1a, /2, PLL2
\ dup h# 4c pmua! ( val )
\ h# 103f or ( val' )
\ dup h# 4c pmua! ( val )
then ( val )
h# 2000 or h# 4c pmua! ( ) \ Enable HDMI ref clock
\ Integer divisor (5), reserved (1<<16), select HDMI CLK (3<<29)
\ 5 1 d# 16 +bits 3 d# 29 +bits h# 9c lcd! \ LCD_TCLK_DIV
5 3 d# 29 +bits h# 9c lcd! \ LCD_TCLK_DIV
;
: lcd-xy! ( hor vert reg# -- ) >r wljoin r> lcd! ;
\ : tv-video-src-res! ( hor vert -- ) wljoin h# 2c lcd! ;
\ : tv-video-dst-res! ( hor vert -- ) wljoin h# 30 lcd! ;
: tv-gfx-base! ( adr -- ) h# 34 lcd! ;
: tv-gfx-pitch! ( pitch -- ) h# 3c lcd! ;
: tv-gfx-offset! ( hor vert -- ) h# 40 lcd-xy! ;
: tv-gfx-src-res! ( hor vert -- ) h# 44 lcd-xy! ;
: tv-gfx-dst-res! ( hor vert -- ) h# 48 lcd-xy! ;
: tv-cursor-pos! ( hor vert -- ) h# 4c lcd-xy! ;
: tv-cursor-size! ( hor vert -- ) h# 50 lcd-xy! ;
: tv-size! ( hor vert -- ) h# 54 lcd-xy! ;
: tv-active! ( hor vert -- ) h# 58 lcd-xy! ;
: tv-porch! ( hfront hback vfront vback -- ) h# 60 lcd-xy! h# 5c lcd-xy! ;
: tv-blank-color! ( color -- ) h# 64 lcd! ;
: tv-vsync! ( rising falling -- ) h# 7c lcd-xy! ;
: tv-dma-ctrl0! ( n -- ) h# 80 lcd! ; : tv-dma-ctrl0@ ( -- n ) h# 80 lcd@ ;
: tv-dma-ctrl1! ( n -- ) h# 84 lcd! ;
: tv-contrast! ( contrast brightness -- ) h# 88 lcd-xy! ;
: tv-saturation! ( saturation mult -- ) h# 8c lcd-xy! ;
: tv-hue! ( cos sin -- ) h# 90 lcd-xy! ;
: tv-tvif! ( n -- ) h# 94 lcd! ; : tv-tvif@ ( -- n ) h# 94 lcd@ ;
: tv-divider! ( n -- ) h# 9c lcd! ;
\ : dither! ( n -- ) h# a0 lcd! ;
\ : dither-table! ( n -- ) h# a4 lcd! ;
d# 16 value tv-bpp
: init-tv-graphics ( -- )
init-tv-clock
0 tv-dma-ctrl0! \ Start with graphics DMA off
0 res@ 1 res@ tv-active!
tv-dma-ctrl0@
1 d# 8 +bits \ DMA enable
h# f d# 16 -bits
0 d# 16 +bits \ Pixel format RGB565
7 d# 9 -bits \ Turn off YUV422PACK, YVYU422P, UYVY422P
1 d# 12 +bits \ RGBswap (RGB, not BGR)
1 d# 27 +bits \ DMA AXI arbiter enable
tv-dma-ctrl0!
\ tv-dma-ctrl1@ h# a00eff00 or tv-dma-ctrl1! \ or h# 2000FF04;
\ h# 283eff00 tv-dma-ctrl1!
h# 2803ff00 tv-dma-ctrl1!
h# f4 lcd@ tv-gfx-base! \ Same base address as DCON panel
hdisp vdisp tv-gfx-src-res! \ Same source res as DCON panel
hdisp bytes/pixel * tv-gfx-pitch!
0 res@ 1 res@ tv-gfx-dst-res!
h# 00ff1000 tv-tvif! \ XXX check this
\ hbp hres+hbp
d# 11 res@ dup 0 res@ + tv-vsync!
\ htotal vtotal
3 res@ 5 res@ tv-size!
\ hfp hbp vfp vbp
d# 10 res@ d# 11 res@ d# 13 res@ d# 14 res@ tv-porch!
\ /* deafult registers */
\ BU_REG_WRITE( LCD_SRAM_CTRL, 0 );
\ BU_REG_WRITE( LCD_SRAM_WRDAT, 0 );
\ BU_REG_WRITE( LCD_SRAM_PARA0, 0 );
\ BU_REG_WRITE( LCD_SRAM_PARA1, 0x0 );
h# 4000 0 tv-contrast!
h# 4000 h# 2000 tv-saturation!
h# 4000 0 tv-hue!
h# 1bc lcd@ h# 30 or h# 1bc lcd! \ PN_IOPAD_CONTROL - 1K boundary, burst 16
h# 1dc lcd@ h# fff0 or h# 1dc lcd! \ LCD_TOP_CTRL - burst lengths
tv-tvif@ 1 or tv-tvif! \ Enable
;
: start-hdmi ( h v -- )
\ XXX need to do monitor detection and use EDID to find its resolutions
find-resolution abort" Unsupported resolution" ( )
init-tv-graphics
hdmi-video-cfg
;
: 720p d# 1280 d# 720 start-hdmi ;
: 1080p d# 1920 d# 1080 start-hdmi ;
also forth definitions
: 1080p ( -- ) " 1080p" $call-screen ;
: 720p ( -- ) " 720p" $call-screen ;
previous definitions
\ /* A:B means that g_res_support[B] = 1 if videoID == A */
\ /* 1:3 2:0 3:0 4:1 8:4 9:4 12:7 13:7 14:8 15:8 16:2 17:2 18:2 */
\ /* 21:10 22:10 23:6 24:6 27:9 28:9 35:11 36:11 37:12 38:12 */
\ static enum edid_returns edid_parseSVD(unsigned char *data_buf,unsigned char svd_len) // Short Video Descriptor
\ {
\ for (unsigned char dataOfs = 0; ++dataOfs <= svd_len; ) { // Skip the header
\ unsigned char videoID = (data_buf[dataOfs] & 0x7F); // Parse SVD
\ if (videoID == 0 || videoID >= sizeof(video_code_map)/sizeof(struct cea_res_info)) { continue; } /* Don't add it */
\ switch (videoID){
\ /* See comment above */
\ }
\ }
\ return EDID_ERR_OK;
\ }
\ LICENSE_BEGIN
\ Copyright (c) 2010 FirmWorks
\
\ Permission is hereby granted, free of charge, to any person obtaining
\ a copy of this software and associated documentation files (the
\ "Software"), to deal in the Software without restriction, including
\ without limitation the rights to use, copy, modify, merge, publish,
\ distribute, sublicense, and/or sell copies of the Software, and to
\ permit persons to whom the Software is furnished to do so, subject to
\ the following conditions:
\
\ The above copyright notice and this permission notice shall be
\ included in all copies or substantial portions of the Software.
\
\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
\ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
\ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
\ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\
\ LICENSE_END