Google
 

Open Sound System
The Hitchhiker's Guide to OSS 4.1 Internals

Do you have problems with sound/audio application development? Don't panic! Click here for help!

oss_hdaudio/hdaudio_si3055.c

Driver for Si3055 and compatible modems.

Description




This file is part of Open Sound System.

Copyright (C) 4Front Technologies 1996-2008.

This this source file is released under GPL v2 license (no other versions). See the COPYING file included in the main directory of this source distribution for the license terms and conditions.




Documentation Note

There is no publicly available documentation for Si3055. However, there is a very similar modem (Si3038) for which a datasheet is publicly available:

https://www.silabs.com/Support%20Documents/TechnicalDocs/si3038.pdf

This driver was written by reading the ALSA code, looking for a similar modem (Si3038), and figuring out the corresponding Si3055 register IDs for Si3038 registers, again by reading the ALSA code, and by checking the default after-reset values.


#include "oss_hdaudio_cfg.h"
#include "hdaudio.h"
#include "hdaudio_codec.h"
#include "hdaudio_dedicated.h"
#include "hdaudio_mixers.h"


Si3055 register IDs.

#define SI3055_EXT_MODEM_STATUS 2
#define SI3055_LINE_RATE  3
#define SI3055_HDA_STREAMS      4
#define SI3055_GPIO_CONFIG      5
#define SI3055_GPIO_PIN_STATUS  10
#define SI3055_LINE_CONFIG      13



SI3055_EXT_MODEM_STATUS 3Eh (Extended Modem Status & Control) SI3055_LINE_RATE 40h (Line 1 DAC/ADC Rate) SI3055_GPIO_PIN_STATUS 54h (GPIO Pin Status) SI3055_LINE_CONFIG 56h (Line Side Configuration 1)



The SI3055_HDA_STREAMS register has no corresponding in Si3038. It contains the playback and recording stream descriptors in the following format:

((playback_stream_num << 4) << 8) | (recording_stream_num << 4)


/* Si3055 verbs. */
#define SI3055_REG_GET_VERB     0x900
#define SI3055_REG_SET_VERB     0x100

/* Convenience macros for reading from and writing to Si3055 registers. */
#define SI3055_REG_GET(mixer, cad, reg, a, b) corb_read(mixer, cad, reg, 0, SI3055_REG_GET_VERB, 0, a, b)
#define SI3055_REG_SET(mixer, cad, reg, val)  corb_write(mixer, cad, reg, 0, SI3055_REG_SET_VERB, val)


void hdaudio_si3055_set_rate(hdaudio_mixer_t *mixer, int cad, int rate)
{
  SI3055_REG_SET(mixer, cad, SI3055_LINE_RATE, rate);
}

int hdaudio_si3055_set_offhook(hdaudio_mixer_t *mixer, int cad, int offhook)
{
  unsigned int a, b;
  SI3055_REG_GET(mixer, cad, SI3055_GPIO_PIN_STATUS, &a, &b);

  if (offhook)
    {
      a |= 0x1;    /* Set Off-Hook bit */
    }
  else
    {
      a &= ~0x1;   /* Unset Off-Hook bit */
    }

  SI3055_REG_SET(mixer, cad, SI3055_GPIO_PIN_STATUS, a);
  SI3055_REG_GET(mixer, cad, SI3055_GPIO_PIN_STATUS, &a, &b);
  return ((a & 0x1) == 0x1);
}

void hdaudio_si3055_endpoint_init(hdaudio_mixer_t *mixer, int cad)
{
  codec_t *codec = mixer->codecs[cad];  /* Modem codec */
  widget_t *widget;                     /* MFG widget */
  hdaudio_endpointinfo_t *endpoint;
  unsigned int a, b;      /* Used for reading data. */
  int tmout;              /* Timeout counter. */

  /* Output and input stream numbers. */
  int playback_stream_num, recording_stream_num;

  
  DDB(cmn_err(CE_CONT, "hdaudio_si3055_endpoint_init got called.\n"));

  /* Reset the modem codec. */
  corb_write(mixer, cad, 0x00, 0, SET_CODEC_RESET, 0);
  corb_write(mixer, cad, codec->afg, 0, SET_CONVERTER, IDDLE_STREAM << 4);
  corb_write(mixer, cad, codec->afg, 0, SET_CONVERTER_FORMAT, 0);
  

It can be changed later when desired.

  SI3055_REG_SET(mixer, cad, SI3055_LINE_RATE, 9600);
  

stream descriptors (ref. HDAudio_03.pdf, page 40).

  SI3055_REG_SET(mixer, cad, SI3055_HDA_STREAMS, 0x0000);
  

to power up the modem (ref. si3038.pdf, page 22).

  SI3055_REG_SET(mixer, cad, SI3055_EXT_MODEM_STATUS, 0x0000);
  

indicate that it is ready (ref. si3038.pdf, page 22).

  tmout = 10;
  do
    {
      SI3055_REG_GET(mixer, cad, SI3055_EXT_MODEM_STATUS, &a, &b);
      DDB(cmn_err(CE_CONT, "si3055: ext modem status: %04x.\n", a));
      oss_udelay(1000);
    }
    while(((a & 0xf) == 0) && --tmout);
  
  if ((a & 0xf) == 0)
    {
      cmn_err(CE_WARN, "si3055: power up timeout (status: %04x).\n", a);
    }
  

to zero to get the modem working. No corresponding register could be found in the Si3038 datasheet.

  SI3055_REG_SET(mixer, cad, SI3055_GPIO_CONFIG, 0x0000);


a reset is 0xF010. Set it to 0x0010 to unmute the analog receive and transmit paths.

  SI3055_REG_SET(mixer, cad, SI3055_LINE_CONFIG, 0x0010);
      
  /* Setup the widget info. */
  widget = &codec->widgets[codec->afg];
  widget->endpoint = &codec->inendpoints[0];
  widget->sizes = 0x20000; /* 16 bits */
  strcpy(widget->name, "modem");

  /* Setup the output endpoint. */
  codec->num_outendpoints = 1;
  endpoint = &codec->outendpoints[0];
  endpoint->ix = 0;
  endpoint->iddle_stream = 0;
  endpoint->cad = cad;
  endpoint->base_wid = codec->afg;
  endpoint->recsrc_wid = endpoint->volume_wid = -1;
  endpoint->nrates = 3;
  endpoint->rates[0] = 8000;
  endpoint->rates[1] = 9600;
  endpoint->rates[2] = 16000;
  endpoint->name = widget->name;
  endpoint->channels = 1;
  endpoint->is_digital = 0;
  endpoint->is_modem = 1;
  endpoint->sizemask = widget->sizes;
  endpoint->fmt_mask = AFMT_S16_LE;
  endpoint->afg = codec->afg;
  endpoint->min_rate = 8000;
  endpoint->max_rate = 16000;
  
  /* Setup the input endpoint. */
  codec->num_inendpoints = 1;
  memcpy(&codec->inendpoints[0], endpoint, sizeof(*endpoint));

  /* Choose stream numbers for output and input streams. */
  playback_stream_num = ++mixer->num_outendpoints;
  endpoint->stream_number = endpoint->default_stream_number = playback_stream_num;

  endpoint = &codec->inendpoints[0];
  recording_stream_num = ++mixer->num_inendpoints;
  endpoint->stream_number = endpoint->default_stream_number = recording_stream_num;

  /* Setup the stream numbers. */
  SI3055_REG_SET(mixer, cad, SI3055_HDA_STREAMS, ((playback_stream_num  << 4) << 8) |
                                                  (recording_stream_num << 4));
}


Copyright (C) 4Front Technologies, 2007. All rights reserved.

Back to index OSS web site


Copyright (C) 4Front Technologies, 2007. All rights reserved.
Back to index OSS web site