File Coverage

blib/lib/Device/I2C/ADV7611.pm
Criterion Covered Total %
statement 44 194 22.6
branch 0 6 0.0
condition 0 12 0.0
subroutine 15 70 21.4
pod 1 55 1.8
total 60 337 17.8


line stmt bran cond sub pod time code
1 1     1   12896 use strict;
  1         1  
  1         24  
2 1     1   3 use warnings;
  1         1  
  1         46  
3              
4             package Device::I2C::ADV7611;
5              
6             # PODNAME: Device::I2C::ADV7611
7             # ABSTRACT: I2C interface to ADV7611 using Device::I2C
8             #
9             # This file is part of Device-I2C-ADV7611
10             #
11             # This software is copyright (c) 2016 by Slava Volkov.
12             #
13             # This is free software; you can redistribute it and/or modify it under
14             # the same terms as the Perl 5 programming language system itself.
15             #
16             our $VERSION = '0.11'; # VERSION
17              
18             # Dependencies
19 1     1   15 use 5.010;
  1         2  
20 1     1   398 use Device::I2C;
  1         7762  
  1         36  
21 1     1   4 use Fcntl;
  1         1  
  1         141  
22 1     1   4 use Carp;
  1         1  
  1         39  
23              
24 1     1   3 use constant CTRL_IO => 0x4c;
  1         2  
  1         43  
25 1     1   3 use constant CTRL_HDMI => 0x34;
  1         2  
  1         31  
26 1     1   3 use constant CTRL_DPLL => 0x3F;
  1         4  
  1         35  
27 1     1   11 use constant CTRL_CEC => 0x40;
  1         1  
  1         34  
28 1     1   3 use constant CTRL_INFO => 0x3E;
  1         2  
  1         32  
29 1     1   3 use constant CTRL_KSV => 0x32;
  1         1  
  1         28  
30 1     1   3 use constant CTRL_EDID => 0x36;
  1         1  
  1         30  
31 1     1   3 use constant CTRL_CP => 0x22;
  1         0  
  1         30  
32              
33 1     1   2 use Exporter qw(import);
  1         1  
  1         1342  
34             our @EXPORT_OK = qw(CTRL_IO CTRL_HDMI CTRL_DPLL CTRL_CEC
35             CTRL_INFO CTRL_KSV CTRL_EDID CTRL_CP );
36             our @ISA = qw(Device::I2C);
37              
38             sub new {
39 0     0 1   my $class = shift;
40 0 0         @_ == 1
41             or croak "usage: $class->new(DEVICENAME)";
42 0           my $io = Device::I2C->new( $_[0], O_RDWR );
43 0 0         if ( !$io ) {
44 0           croak "Unable to open I2C Device File at $_[0]";
45 0           return undef;
46             }
47 0           bless( $io, $class );
48 0           $io;
49             }
50              
51             sub resetDevice {
52 0     0 0   `echo 0 > /proc/v2r_gpio/98`;
53 0           `echo 1 > /proc/v2r_gpio/98`;
54 0           `echo 0 > /proc/v2r_gpio/99`;
55 0           `echo 1 > /proc/v2r_gpio/99`;
56 0           `echo 0 > /proc/v2r_gpio/pwctr2`;
57 0           sleep(1);
58 0           `echo 1 > /proc/v2r_gpio/pwctr2`;
59             }
60              
61             sub writeRegister {
62 0     0 0   my ( $io, $addr, $register, $value ) = @_;
63 0           $io->selectDevice($addr);
64 0           $io->writeByteData( $register, $value );
65             }
66              
67             sub readRegister {
68 0     0 0   my ( $io, $addr, $register ) = @_;
69 0           $io->selectDevice($addr);
70 0           return $io->readByteData($register);
71             }
72              
73             sub readRegister16 {
74 0     0 0   my ( $io, $addr, $register ) = @_;
75 0           $io->selectDevice($addr);
76 0           my $res = $io->readByteData($register);
77 0           $res <<= 8;
78 0           return $res + $io->readByteData( $register + 1 );
79             }
80              
81             sub writeIO {
82 0     0 0   my ( $io, $register, $value ) = @_;
83 0           $io->writeRegister( CTRL_IO, $register, $value );
84             }
85              
86             sub readIO {
87 0     0 0   my ( $io, $register ) = @_;
88 0           $io->readRegister( CTRL_IO, $register );
89             }
90              
91             sub readIO16 {
92 0     0 0   my ( $io, $register ) = @_;
93 0           $io->readRegister16( CTRL_IO, $register );
94             }
95              
96             sub writeHDMI {
97 0     0 0   my ( $io, $register, $value ) = @_;
98 0           $io->writeRegister( CTRL_HDMI, $register, $value );
99             }
100              
101             sub readHDMI {
102 0     0 0   my ( $io, $register ) = @_;
103 0           $io->readRegister( CTRL_HDMI, $register );
104             }
105              
106             sub readHDMI16 {
107 0     0 0   my ( $io, $register ) = @_;
108 0           $io->readRegister16( CTRL_HDMI, $register );
109             }
110              
111             sub writeDPLL {
112 0     0 0   my ( $io, $register, $value ) = @_;
113 0           $io->writeRegister( CTRL_DPLL, $register, $value );
114             }
115              
116             sub readDPLL {
117 0     0 0   my ( $io, $register ) = @_;
118 0           $io->readRegister( CTRL_DPLL, $register );
119             }
120              
121             sub writeCEC {
122 0     0 0   my ( $io, $register, $value ) = @_;
123 0           $io->writeRegister( CTRL_CEC, $register, $value );
124             }
125              
126             sub readCEC {
127 0     0 0   my ( $io, $register ) = @_;
128 0           $io->readRegister( CTRL_CEC, $register );
129             }
130              
131             sub writeINFO {
132 0     0 0   my ( $io, $register, $value ) = @_;
133 0           $io->writeRegister( CTRL_INFO, $register, $value );
134             }
135              
136             sub readINFO {
137 0     0 0   my ( $io, $register ) = @_;
138 0           $io->readRegister( CTRL_INFO, $register );
139             }
140              
141             sub writeKSV {
142 0     0 0   my ( $io, $register, $value ) = @_;
143 0           $io->writeRegister( CTRL_KSV, $register, $value );
144             }
145              
146             sub readKSV {
147 0     0 0   my ( $io, $register ) = @_;
148 0           $io->readRegister( CTRL_KSV, $register );
149             }
150              
151             sub writeEDID {
152 0     0 0   my ( $io, $register, $value ) = @_;
153 0           $io->writeRegister( CTRL_EDID, $register, $value );
154             }
155              
156             sub readEDID {
157 0     0 0   my ( $io, $register ) = @_;
158 0           $io->readRegister( CTRL_EDID, $register );
159             }
160              
161             sub writeCP {
162 0     0 0   my ( $io, $register, $value ) = @_;
163 0           $io->writeRegister( CTRL_CP, $register, $value );
164             }
165              
166             sub readCP {
167 0     0 0   my ( $io, $register ) = @_;
168 0           $io->readRegister( CTRL_CP, $register );
169             }
170              
171             sub readCP16 {
172 0     0 0   my ( $io, $register ) = @_;
173 0           $io->readRegister16( CTRL_CP, $register );
174             }
175              
176             sub initAddressMaps {
177 0     0 0   my ($io) = @_;
178              
179 0           $io->writeIO( 0xfd, CTRL_CP << 1 );
180 0           $io->writeIO( 0xf9, CTRL_KSV << 1 );
181 0           $io->writeIO( 0xfb, CTRL_HDMI << 1 );
182 0           $io->writeIO( 0xfa, CTRL_EDID << 1 );
183 0           $io->writeIO( 0xf8, CTRL_DPLL << 1 );
184 0           $io->writeIO( 0xf4, CTRL_CEC << 1 );
185 0           $io->writeIO( 0xf5, CTRL_INFO << 1 );
186             }
187              
188             sub writeEDIDTable {
189 0     0 0   my ( $io, @edid ) = @_;
190 0           my $err;
191              
192 0           $io->writeKSV( 0x40, 0x81 ); # Disable HDCP 1.1
193 0           $io->writeKSV( 0x74, 0x00 ); # disable internal EDID
194              
195 0           my $count = @edid;
196 0           printf( "Write edid data %d bytes\n", $count );
197              
198 0           for ( my $i = 0 ; $i < $count ; $i++ ) {
199              
200             #printf("EDID %x, %x\n", $i, $edid[$i]);
201 0           $err = $io->writeEDID( $i, $edid[$i] );
202 0 0         if ( $err < 0 ) {
203 0           printf("fail to write edid data\n");
204 0           return;
205              
206             # ADV761x calculates the checksums and enables I2C access
207             # to internal EDID ram from DDC port.
208             }
209             }
210              
211 0           $io->writeKSV( 0x74, 0x01 ); # enable internal EDID
212 0           $io->writeIO( 0x15, 0xBE );
213             }
214              
215             # check line state
216             sub noPower {
217 0     0 0   my ($io) = @_;
218 0           return $io->readIO(0x0c) & 0x24;
219             }
220              
221             sub checkCable {
222 0     0 0   my ($io) = @_;
223 0           return $io->readIO(0x6f) & 0x01;
224             }
225              
226             sub isHDMI {
227 0     0 0   my ($io) = @_;
228 0           return $io->readHDMI(0x05) & 0x80;
229             }
230              
231             sub isDERegenFilterLocked {
232 0     0 0   my ($io) = @_;
233 0           return $io->readHDMI(0x07) & 0x20;
234             }
235              
236             sub isVertFilterLocked {
237 0     0 0   my ($io) = @_;
238 0           return $io->readHDMI(0x07) & 0x80;
239             }
240              
241             sub isFiltersLocked {
242 0     0 0   my ($io) = @_;
243 0   0       return $io->isDERegenFilterLocked() && $io->isVertFilterLocked();
244             }
245              
246             sub isLockSTDI {
247 0     0 0   my ($io) = @_;
248 0           return $io->readCP(0xb1) & 0x80;
249             }
250              
251             sub isTMDS {
252 0     0 0   my ($io) = @_;
253 0           return $io->readIO(0x6a) & 0x10;
254             }
255              
256             sub isLockTMDS {
257 0     0 0   my ($io) = @_;
258 0           return $io->readIO(0x6a) & 0x43 == 0x43;
259             }
260              
261             sub isInterlaced {
262 0     0 0   my ($io) = @_;
263 0           return $io->readIO(0x12) & 0x10;
264             }
265              
266             sub isSignal {
267 0     0 0   my ($io) = @_;
268 0           my $res;
269 0           $res = !$io->noPower();
270 0   0       $res &&= $io->isLockSTDI();
271 0   0       $res &&= $io->isTMDS();
272 0   0       $res &&= $io->isLockTMDS();
273             }
274              
275             sub isFreeRun {
276 0     0 0   my ($io) = @_;
277 0           return $io->readCP(0xff) & 0x10;
278             }
279              
280             # HDMI signal params
281             sub getTotalWidth {
282 0     0 0   my ($io) = @_;
283 0           return $io->readHDMI16(0x1e) & 0x3fff;
284             }
285              
286             sub getWidth {
287 0     0 0   my ($io) = @_;
288 0           return $io->readHDMI16(0x07) & 0x1fff;
289             }
290              
291             sub getTotalHeight0 {
292 0     0 0   my ($io) = @_;
293 0           return ( $io->readHDMI16(0x26) & 0x3fff ) / 2;
294             }
295              
296             sub getTotalHeight1 {
297 0     0 0   my ($io) = @_;
298 0           return ( $io->readHDMI16(0x28) & 0x3fff ) / 2;
299             }
300              
301             sub getHeight0 {
302 0     0 0   my ($io) = @_;
303 0           return $io->readHDMI16(0x09) & 0x1fff;
304             }
305              
306             sub getHeight1 {
307 0     0 0   my ($io) = @_;
308 0           return $io->readHDMI16(0x0b) & 0x1fff;
309             }
310              
311             sub getHFrontPorch {
312 0     0 0   my ($io) = @_;
313 0           return $io->readHDMI16(0x20) & 0x1fff;
314             }
315              
316             sub getHSync {
317 0     0 0   my ($io) = @_;
318 0           return $io->readHDMI16(0x22) & 0x1fff;
319             }
320              
321             sub getHBackPorch {
322 0     0 0   my ($io) = @_;
323 0           return $io->readHDMI16(0x24) & 0x1fff;
324             }
325              
326             sub getVFrontPorch0 {
327 0     0 0   my ($io) = @_;
328 0           return ( $io->readHDMI16(0x2a) & 0x3fff ) / 2;
329             }
330              
331             sub getVFrontPorch1 {
332 0     0 0   my ($io) = @_;
333 0           return ( $io->readHDMI16(0x2c) & 0x3fff ) / 2;
334             }
335              
336             sub getVSync0 {
337 0     0 0   my ($io) = @_;
338 0           return ( $io->readHDMI16(0x2e) & 0x3fff ) / 2;
339             }
340              
341             sub getVSync1 {
342 0     0 0   my ($io) = @_;
343 0           return ( $io->readHDMI16(0x30) & 0x3fff ) / 2;
344             }
345              
346             sub getVBackPorch0 {
347 0     0 0   my ($io) = @_;
348 0           return ( $io->readHDMI16(0x32) & 0x3fff ) / 2;
349             }
350              
351             sub getVBackPorch1 {
352 0     0 0   my ($io) = @_;
353 0           return ( $io->readHDMI16(0x34) & 0x3fff ) / 2;
354             }
355              
356             sub getFPS1000 {
357 0     0 0   my ($io) = @_;
358 0           my $fps = $io->readCP16(0xb8) & 0x1fff;
359 0           return 28636360 / 256 / $fps * 1000;
360             }
361              
362             sub getTMDSFreq {
363 0     0 0   my ($io) = @_;
364 0           my $freq = $io->readHDMI16(0x51);
365 0           my $frac = ( $freq & 0x7f ) / 128;
366 0           return ( $freq >> 7 ) + $frac;
367             }
368              
369             1;
370              
371             __END__