| 1 | #ifdef HAVE_XORG_CONFIG_H |
| 2 | #include <xorg-config.h> |
| 3 | #endif |
| 4 | |
| 5 | #include "xf86.h" |
| 6 | #include "xf86i2c.h" |
| 7 | #include "tda9885.h" |
| 8 | #include "i2c_def.h" |
| 9 | |
| 10 | TDA9885Ptr |
| 11 | Detect_tda9885(I2CBusPtr b, I2CSlaveAddr addr) |
| 12 | { |
| 13 | TDA9885Ptr t; |
| 14 | I2CByte a; |
| 15 | |
| 16 | t = calloc(1, sizeof(TDA9885Rec)); |
| 17 | if (t == NULL) |
| 18 | return NULL; |
| 19 | switch (addr) { |
| 20 | case TDA9885_ADDR_1: |
| 21 | case TDA9885_ADDR_2: |
| 22 | case TDA9885_ADDR_3: |
| 23 | case TDA9885_ADDR_4: |
| 24 | t->d.DevName = "TDA9885 Alignment-free IF-PLL"; |
| 25 | break; |
| 26 | default: |
| 27 | t->d.DevName = "Generic TDAxxxx"; |
| 28 | break; |
| 29 | } |
| 30 | t->d.SlaveAddr = addr; |
| 31 | t->d.pI2CBus = b; |
| 32 | t->d.NextDev = NULL; |
| 33 | t->d.StartTimeout = b->StartTimeout; |
| 34 | t->d.BitTimeout = b->BitTimeout; |
| 35 | t->d.AcknTimeout = b->AcknTimeout; |
| 36 | t->d.ByteTimeout = b->ByteTimeout; |
| 37 | |
| 38 | if (!I2C_WriteRead(&(t->d), NULL, 0, &a, 1)) { |
| 39 | free(t); |
| 40 | return NULL; |
| 41 | } |
| 42 | |
| 43 | /* set default parameters */ |
| 44 | if (!I2CDevInit(&(t->d))) { |
| 45 | free(t); |
| 46 | return NULL; |
| 47 | } |
| 48 | |
| 49 | return t; |
| 50 | } |
| 51 | |
| 52 | Bool |
| 53 | tda9885_init(TDA9885Ptr t) |
| 54 | { |
| 55 | t->forced_mute_audio = 1; |
| 56 | return TRUE; |
| 57 | } |
| 58 | |
| 59 | void |
| 60 | tda9885_getstatus(TDA9885Ptr t) |
| 61 | { |
| 62 | CARD8 value; |
| 63 | |
| 64 | I2C_WriteRead(&(t->d), NULL, 0, &value, 1); |
| 65 | t->after_reset = value & 1; |
| 66 | t->afc_status = (value >> 1) & 0xf; |
| 67 | t->fm_carrier = (value >> 5) & 1; |
| 68 | t->vif_level = (value >> 6) & 1; |
| 69 | t->afc_win = (value >> 7) & 1; |
| 70 | } |
| 71 | |
| 72 | void |
| 73 | tda9885_setparameters(TDA9885Ptr t) |
| 74 | { |
| 75 | CARD8 data[4]; |
| 76 | |
| 77 | data[0] = 0; /* start with subaddress 0 */ |
| 78 | data[1] = (t->sound_trap & 1) | ((t->auto_mute_fm & 1) << 1) | ((t->carrier_mode & 1) << 2) | ((t->modulation & 3) << 3) | ((t->forced_mute_audio & 1) << 5) | ((t->port1 & 1) << 6) | ((t->port2 & 1) << 7); /* B data */ |
| 79 | data[2] = (t->top_adjustment & 0x1f) | ((t->deemphasis & 0x3) << 5) | ((t->audio_gain & 1) << 7); /* C data */ |
| 80 | data[3] = (t->standard_sound_carrier & 0x3) | ((t->standard_video_if & 0x07) << 2) | ((t->minimum_gain & 0x01) << 5) | ((t->gating & 0x01) << 6) | ((t->vif_agc & 0x01) << 7); /* E data */ |
| 81 | |
| 82 | I2C_WriteRead(&(t->d), data, 4, NULL, 0); |
| 83 | |
| 84 | xf86DrvMsg(t->d.pI2CBus->scrnIndex, X_INFO, |
| 85 | "TDA9885 setparam: B data: %x, C data: %x, E data: %x\n", |
| 86 | data[1], data[2], data[3]); |
| 87 | } |
| 88 | |
| 89 | void |
| 90 | tda9885_dumpstatus(TDA9885Ptr t) |
| 91 | { |
| 92 | xf86DrvMsg(t->d.pI2CBus->scrnIndex, X_INFO, |
| 93 | "TDA9885 status: after_reset=%d afc_status=%d (%3.1f kHz off) fm_carrier=%d vif_level=%d afc_win=%d %s\n", |
| 94 | t->after_reset, t->afc_status, |
| 95 | (t->afc_status < |
| 96 | 8) ? -12.5 - t->afc_status * 25.0 : -12.5 + (16 - |
| 97 | t->afc_status) * |
| 98 | 25.0, t->fm_carrier, t->vif_level, t->afc_win, |
| 99 | t->afc_win ? "VCO in" : "VCO out"); |
| 100 | } |