• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/python2
2
3# Copyright 2014 The Chromium OS Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7# Reference[1]: IT680x example code:
8# https://drive.google.com/corp/drive/u/0/folders/0B8Lcp5hqbjaqaE5WdDA5alVWOXc
9
10# Reference[2]: IT6803 Programming Guide:
11# https://docs.google.com/viewer?a=v&pid=sites&srcid=\
12# Y2hyb21pdW0ub3JnfGRldnxneDoyNGVmNGFiMDE4ZWJiZDM2
13
14# This code is a library for using IT680X chip in chameleon.
15
16from __future__ import print_function
17
18import sys
19import util
20from time import sleep
21
22usage = """\
23Usage:
24  it6803                        -- print command usage
25  it6803 cec_reg_print          -- print all cec registers value
26  it6803 cec_msg_receive        -- print receiving cec message
27  it6803 cec_msg {cmd}          -- send cec message
28"""
29
30QUEUE_SIZE = 3
31q_head = 0
32q_tail = 0
33regTxOutState = 3
34
35logicalAddr = 0
36initiatorAddr = 0x0F
37cecTxState = 0
38
39txCmdBuf = [0x00] * 19
40rxCecBuf = [0x00] * 19
41queue = [[0x00 for i in range(19)] for j in range(QUEUE_SIZE)]
42
43# Chameleon register address
44I2C_HDMI = 0x48
45I2C_CEC = 0x4A
46
47# Chameleon CEC control registers
48# (name starts with REG is register addr, followings are values for this reg)
49REG06         = 0x06
50REG_EMPTY     = 0x00
51REG07         = 0x07
52ENABLE_CEC_INTERRUPT_PIN = 0x40
53
54REG08         = 0x08
55FIRE_FRAME          = 0x80
56DEBUG_CEC_CLEAR     = 0x40
57CEC_SCHMITT_TRIGGER = 0x08
58CEC_INTERRUPT       = 0x01
59
60REG09         = 0x09
61REGION_SELECT    = 0x40
62INITAITOR_RX_CEC = 0x20
63ACKNOWLEDGE      = 0x01
64
65REG_MIN_BIT   = 0x0B
66REG_TIME_UNIT = 0x0C
67
68REG0F         = 0x0F
69IO_PULL_UP    = 0x50
70
71REG_TARG_ADDR = 0x22
72REG_MSCOUNT_L = 0x45
73REG_MSCOUNT_M = 0x46
74REG_MSCOUNT_H = 0x47
75REF_INT_STATUS= 0x4C
76
77def main(cmdline):
78    """ Main function. """
79    args = [''] * 4
80    for i, x in enumerate(cmdline):
81        args[i] = x
82    cmd = args[1]
83
84    if cmd == '': cmd = 'help'
85    fname = 'cmd_' + cmd
86
87    cec_open()
88    if fname in globals():
89        if args[2] == '':
90            globals()[fname]()
91        else:
92            globals()[fname](args[2])
93    else:
94        print('Unknown command', cmd)
95    cec_close()
96
97
98def cmd_help():
99    """ Print help message. """
100    print(usage)
101
102
103def cec_open():
104    """ Enable cec port. """
105    # enable IT6803 CEC port: enable cec clock and assign slave addr
106    i2cset(I2C_HDMI, 0x0E, 0xFF)
107    i2cset(I2C_HDMI, 0x86, 0x95)
108
109def cec_close():
110    """ Close cec port. """
111    # disable cec slave addr
112    i2cset(I2C_HDMI, 0x86, 0x94)
113
114
115def cec_init():
116    """ Initialize cec port in chameleon. """
117    # initial CEC register. From reference[1] Ln480
118
119    # enable it680x cec
120    i2cset(I2C_CEC, 0xF8, 0xC3)
121    i2cset(I2C_CEC, 0xF8, 0xA5)
122    q_head = 0
123    q_tail = 0
124    regTxOutState = 3
125
126    # get 100ms timer, according to ref [1,2]
127    i2cset(I2C_CEC, REG09, ACKNOWLEDGE)
128    sleep(0.099)
129    i2cset(I2C_CEC, REG09, REG_EMPTY)
130    high  = util.i2c_read(0, I2C_CEC, REG_MSCOUNT_H, 1)[0] * 0x10000
131    mid   = util.i2c_read(0, I2C_CEC, REG_MSCOUNT_M, 1)[0] * 0x100
132    low   = util.i2c_read(0, I2C_CEC, REG_MSCOUNT_L, 1)[0]
133    tus = (high + mid + low) / 1000
134    # print tus
135
136    # CEC configuration
137    i2cset(I2C_CEC, REG09, INITAITOR_RX_CEC | REGION_SELECT)
138    i2cset(I2C_CEC, REG_MIN_BIT, 0x14)
139    i2cset(I2C_CEC, REG_TIME_UNIT, tus)
140    i2cset(I2C_CEC, REG_TARG_ADDR, logicalAddr)
141    i2cset(I2C_CEC, REG08, CEC_SCHMITT_TRIGGER)
142    uc = util.i2c_read(0, I2C_CEC, REG09, 1)[0]
143    # i2cset(I2C_CEC, REG09, uc|0x02)
144    # cec_clr_int
145    i2cset(I2C_CEC, REG08, CEC_INTERRUPT|DEBUG_CEC_CLEAR|CEC_SCHMITT_TRIGGER)
146    i2cset(I2C_CEC, REG08, CEC_SCHMITT_TRIGGER|DEBUG_CEC_CLEAR)
147    # print 'logicalAddr: {}, TimeUnit: {}'.format(logicalAddr,tus)
148
149    # Enable CEC interrupt pin
150    reg07_val = util.i2c_read(0, I2C_CEC, REG07, 1)[0]
151    i2cset(I2C_CEC, REG07, reg07_val | ENABLE_CEC_INTERRUPT_PIN)
152
153    # Enable ALL interrupt mask
154    i2cset(I2C_CEC, REG06, REG_EMPTY)
155
156    # IO pull up enable
157    i2cset(I2C_CEC, REG0F, IO_PULL_UP)
158
159def cec_msg_receive():
160    """ Read message received. """
161    # 0x3F means all interrupts are on
162    cecInt = cec_reg_read(REF_INT_STATUS) & 0x3F
163    if 0 != (cecInt & 0x10):
164        if not cec_msg_read():
165            raise Exception('Queue is full!')
166    ## TODO check interrupt register Status
167    i2c_cec_set(REF_INT_STATUS, cecInt)
168    # Decode received message
169    return cec_decode()
170
171
172def cmd_cec_msg(message):
173    """ parent function for a cec message. """
174    cec_init()
175    fname = 'cec_msg_' + message
176    globals()[fname]()
177    cec_transmit()
178
179def cec_msg_standby():
180    """ Send a stand by message. """
181    # F = boardcast, 0x36 = stand by message
182    cec_cmd_set(0xF, 0x36, None, None)
183    # other operations need more assignments
184
185def cec_msg_viewon():
186    """ Send a view on message. """
187    # 0 = TV, 0x04 = image on
188    cec_cmd_set(0x0, 0x04, None, None)
189
190def cec_msg_poweron():
191    """ Make a power on cec message. """
192    global initiatorAddr
193    # 0x90 = power status message
194    cec_cmd_set(initiatorAddr, 0x90, 0x00, None)
195
196def cec_msg_poweroff():
197    """ Make a power off cec message. """
198    global initiatorAddr
199    # 0x90 = power status message
200    cec_cmd_set(initiatorAddr, 0x90, 0x01, None)
201
202def cec_reg_read(offset):
203    """ read it6803's register value from i2c line. """
204    return util.i2c_read(0, I2C_CEC, offset, 1)[0]
205
206def cec_cmd_set(follower, txCmd, operand1, operand2):
207    """ Compose a cec message. """
208    # print 'follower: {}, cmd: {}'.format(follower, txCmd)
209    # TODO set variables
210    txCmdBuf[0] = 2
211    txCmdBuf[1] = (logicalAddr<<4) + follower
212    txCmdBuf[2] = txCmd
213    txCmdBuf[3] = 0
214    txCmdBuf[4] = 0
215    if operand1 is not None:
216        txCmdBuf[3] = operand1
217        txCmdBuf[0] = 3
218    if operand2 is not None:
219        txCmdBuf[4] = operand2
220        txCmdBuf[0] = 4
221    # print txCmdBuf
222    return
223
224def cec_transmit():
225    """ File a cec message out. """
226    # Assume the state is cecTransfer
227    # Set values from 0x10 to 0x23
228    i2c_cec_set(0x23, txCmdBuf[0])
229    for i in range (0, txCmdBuf[0]):
230        i2c_cec_set(0x10+i, txCmdBuf[i+1])
231
232    # Fire command
233    i2c_cec_set(REG08, FIRE_FRAME | CEC_SCHMITT_TRIGGER | DEBUG_CEC_CLEAR)
234    i2c_cec_set(REG08, CEC_SCHMITT_TRIGGER | DEBUG_CEC_CLEAR)
235    return
236
237def cec_msg_read():
238    """ Read incoming cec messages from memory. """
239    global q_head, q_tail
240    if (q_head % QUEUE_SIZE) != (q_tail % QUEUE_SIZE):
241        return False
242    q_tail += 1
243    i = q_tail % QUEUE_SIZE
244    # 0x30 is starting point for receiving message
245    data = util.i2c_read(0, I2C_CEC, 0x30, 19)
246    for j in range(1, 19):
247        queue[i][j] = data[j-1]
248    queue[i][0] = data[18]
249    return True
250
251def cec_decode():
252    """ Process incoming cec message. """
253    global q_head, q_tail, initiatorAddr
254    if (q_head % QUEUE_SIZE) == (q_tail % QUEUE_SIZE):
255        # Queue is empty
256        return
257    q_head += 1
258    rxCecBuf = queue[q_head % QUEUE_SIZE]
259    #print rxCecBuf
260
261    if (rxCecBuf[0] == 1):
262        if logicalAddr == (rxCecBuf[1] & 0x0F):
263            # eReportPhysicalAddress
264            return
265    # Validate message
266    initiatorAddr = (rxCecBuf[1] >> 4) & 0x0F
267    followerAddr = rxCecBuf[1] & 0x0F
268    print('Initiator: {} Follower: {}'.format(initiatorAddr, followerAddr))
269
270    if (rxCecBuf[2] == 0x04):
271        print('received image-view-on')
272    elif (rxCecBuf[2] == 0x36):
273        print('received standby')
274    else:
275        print('other command: {}'.format(rxCecBuf[2]))
276    return rxCecBuf[2]
277
278def i2cset(addr, offset, value):
279    """ set some register value via i2c line. """
280    util.i2c_write(0, addr, offset, [value])
281
282def i2c_cec_set(offset, value):
283    """ set it6803's register value via i2c line. """
284    i2cset(I2C_CEC, offset, value)
285
286if __name__ == '__main__':
287    main(sys.argv)
288