X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=drivers%2Fmedia%2Fcommon%2Fsiano%2Fsmscoreapi.c;h=d57df9170ae1e41415e06605a0e00b9aedfc1d69;hb=e584f9d61ea0aefa81ddd3faf53100536ba4057e;hp=5034153ed09c0b53390a83e95e9b7f19618658a2;hpb=ab7bdb12984732e5ebac00d6a180431cbd4e0ce1;p=~andy%2Flinux diff --git a/drivers/media/common/siano/smscoreapi.c b/drivers/media/common/siano/smscoreapi.c index 5034153ed09..d57df9170ae 100644 --- a/drivers/media/common/siano/smscoreapi.c +++ b/drivers/media/common/siano/smscoreapi.c @@ -37,7 +37,6 @@ #include "smscoreapi.h" #include "sms-cards.h" #include "smsir.h" -#include "smsendian.h" static int sms_dbg; module_param_named(debug, sms_dbg, int, 0644); @@ -435,7 +434,7 @@ static struct mutex g_smscore_deviceslock; static struct list_head g_smscore_registry; static struct mutex g_smscore_registrylock; -static int default_mode = 4; +static int default_mode = DEVICE_MODE_NONE; module_param(default_mode, int, 0644); MODULE_PARM_DESC(default_mode, "default firmware id (device mode)"); @@ -490,10 +489,10 @@ static enum sms_device_type_st smscore_registry_gettype(char *devpath) else sms_err("No registry found."); - return -1; + return -EINVAL; } -void smscore_registry_setmode(char *devpath, int mode) +static void smscore_registry_setmode(char *devpath, int mode) { struct smscore_registry_entry_t *entry; @@ -633,10 +632,11 @@ static struct smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer, dma_addr_t common_buffer_phys) { - struct smscore_buffer_t *cb = - kmalloc(sizeof(struct smscore_buffer_t), GFP_KERNEL); + struct smscore_buffer_t *cb; + + cb = kzalloc(sizeof(struct smscore_buffer_t), GFP_KERNEL); if (!cb) { - sms_info("kmalloc(...) failed"); + sms_info("kzalloc(...) failed"); return NULL; } @@ -710,9 +710,10 @@ int smscore_register_device(struct smsdevice_params_t *params, for (buffer = dev->common_buffer; dev->num_buffers < params->num_buffers; dev->num_buffers++, buffer += params->buffer_size) { - struct smscore_buffer_t *cb = - smscore_createbuffer(buffer, dev->common_buffer, - dev->common_buffer_phys); + struct smscore_buffer_t *cb; + + cb = smscore_createbuffer(buffer, dev->common_buffer, + dev->common_buffer_phys); if (!cb) { smscore_unregister_device(dev); return -ENOMEM; @@ -805,8 +806,6 @@ static int smscore_init_ir(struct smscore_device_t *coredev) msg->msgData[0] = coredev->ir.controller; msg->msgData[1] = coredev->ir.timeout; - smsendian_handle_tx_message( - (struct SmsMsgHdr_ST2 *)msg); rc = smscore_sendrequest_and_wait(coredev, msg, msg->xMsgHeader. msgLength, &coredev->ir_init_done); @@ -822,6 +821,55 @@ static int smscore_init_ir(struct smscore_device_t *coredev) return 0; } +/** + * configures device features according to board configuration structure. + * + * @param coredev pointer to a coredev object returned by + * smscore_register_device + * + * @return 0 on success, <0 on error. + */ +int smscore_configure_board(struct smscore_device_t *coredev) +{ + struct sms_board *board; + + board = sms_get_board(coredev->board_id); + if (!board) { + sms_err("no board configuration exist."); + return -EINVAL; + } + + if (board->mtu) { + struct SmsMsgData_ST MtuMsg; + sms_debug("set max transmit unit %d", board->mtu); + + MtuMsg.xMsgHeader.msgSrcId = 0; + MtuMsg.xMsgHeader.msgDstId = HIF_TASK; + MtuMsg.xMsgHeader.msgFlags = 0; + MtuMsg.xMsgHeader.msgType = MSG_SMS_SET_MAX_TX_MSG_LEN_REQ; + MtuMsg.xMsgHeader.msgLength = sizeof(MtuMsg); + MtuMsg.msgData[0] = board->mtu; + + coredev->sendrequest_handler(coredev->context, &MtuMsg, + sizeof(MtuMsg)); + } + + if (board->crystal) { + struct SmsMsgData_ST CrysMsg; + sms_debug("set crystal value %d", board->crystal); + + SMS_INIT_MSG(&CrysMsg.xMsgHeader, + MSG_SMS_NEW_CRYSTAL_REQ, + sizeof(CrysMsg)); + CrysMsg.msgData[0] = board->crystal; + + coredev->sendrequest_handler(coredev->context, &CrysMsg, + sizeof(CrysMsg)); + } + + return 0; +} + /** * sets initial device mode and notifies client hotplugs that device is ready * @@ -832,12 +880,24 @@ static int smscore_init_ir(struct smscore_device_t *coredev) */ int smscore_start_device(struct smscore_device_t *coredev) { - int rc = smscore_set_device_mode( - coredev, smscore_registry_getmode(coredev->devpath)); + int rc; + int board_id = smscore_get_board_id(coredev); + int mode = smscore_registry_getmode(coredev->devpath); + + /* Device is initialized as DEVICE_MODE_NONE */ + if (board_id != SMS_BOARD_UNKNOWN && mode == DEVICE_MODE_NONE) + mode = sms_get_board(board_id)->default_mode; + + rc = smscore_set_device_mode(coredev, mode); if (rc < 0) { sms_info("set device mode faile , rc %d", rc); return rc; } + rc = smscore_configure_board(coredev); + if (rc < 0) { + sms_info("configure board failed , rc %d", rc); + return rc; + } kmutex_lock(&g_smscore_deviceslock); @@ -931,7 +991,6 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev, /* Entry point */ msg->msgData[1] = firmware->Length; msg->msgData[2] = 0; /* Regular checksum*/ - smsendian_handle_tx_message(msg); rc = smscore_sendrequest_and_wait(coredev, msg, msg->xMsgHeader.msgLength, &coredev->data_validity_done); @@ -955,14 +1014,12 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev, TriggerMsg->msgData[3] = 0; /* Parameter */ TriggerMsg->msgData[4] = 4; /* Task ID */ - smsendian_handle_tx_message((struct SmsMsgHdr_S *)msg); rc = smscore_sendrequest_and_wait(coredev, TriggerMsg, TriggerMsg->xMsgHeader.msgLength, &coredev->trigger_done); } else { SMS_INIT_MSG(&msg->xMsgHeader, MSG_SW_RELOAD_EXEC_REQ, sizeof(struct SmsMsgHdr_ST)); - smsendian_handle_tx_message((struct SmsMsgHdr_S *)msg); rc = coredev->sendrequest_handler(coredev->context, msg, msg->xMsgHeader.msgLength); } @@ -977,18 +1034,21 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev, msleep(400); exit_fw_download: - sms_debug("rc=%d, postload=0x%p ", rc, coredev->postload_handler); - kfree(msg); - return ((rc >= 0) && coredev->postload_handler) ? - coredev->postload_handler(coredev->context) : - rc; + if (coredev->postload_handler) { + sms_debug("rc=%d, postload=0x%p", rc, coredev->postload_handler); + if (rc >= 0) + return coredev->postload_handler(coredev->context); + } + + sms_debug("rc=%d", rc); + return rc; } static char *smscore_get_fw_filename(struct smscore_device_t *coredev, - int mode, int lookup); + int mode); /** * loads specified firmware into a buffer and calls device loadfirmware_handler @@ -1001,7 +1061,7 @@ static char *smscore_get_fw_filename(struct smscore_device_t *coredev, * @return 0 on success, <0 on error. */ static int smscore_load_firmware_from_file(struct smscore_device_t *coredev, - int mode, int lookup, + int mode, loadfirmware_t loadfirmware_handler) { int rc = -ENOENT; @@ -1009,10 +1069,12 @@ static int smscore_load_firmware_from_file(struct smscore_device_t *coredev, u32 fw_buf_size; const struct firmware *fw; - char *fw_filename = smscore_get_fw_filename(coredev, mode, lookup); - sms_debug("Firmware name: %s\n", fw_filename); - if (!strcmp(fw_filename, "none")) + char *fw_filename = smscore_get_fw_filename(coredev, mode); + if (!fw_filename) { + sms_info("mode %d not supported on this device", mode); return -ENOENT; + } + sms_debug("Firmware name: %s", fw_filename); if (loadfirmware_handler == NULL && !(coredev->device_flags & SMS_DEVICE_FAMILY2)) @@ -1145,32 +1207,53 @@ static int smscore_detect_mode(struct smscore_device_t *coredev) return rc; } -static char *smscore_fw_lkup[][SMS_NUM_OF_DEVICE_TYPES] = { - /*Stellar, NOVA A0, Nova B0, VEGA, VENICE, MING, PELE, RIO, DENVER_1530, DENVER_2160 */ - /*DVBT*/ - { "none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none", "none", "none", "none", "dvb_rio.inp", "none", "none" }, - /*DVBH*/ - { "none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none", "none", "none", "none", "dvbh_rio.inp", "none", "none" }, - /*TDMB*/ - { "none", "tdmb_nova_12mhz.inp", "tdmb_nova_12mhz_b0.inp", "none", "none", "none", "none", "none", "none", "tdmb_denver.inp" }, - /*DABIP*/ - { "none", "none", "none", "none", "none", "none", "none", "none", "none", "none" }, - /*DVBT_BDA*/ - { "none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none", "none", "none", "none", "dvb_rio.inp", "none", "none" }, - /*ISDBT*/ - { "none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none", "none", "none", "isdbt_pele.inp", "isdbt_rio.inp", "none", "none" }, - /*ISDBT_BDA*/ - { "none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none", "none", "none", "isdbt_pele.inp", "isdbt_rio.inp", "none", "none" }, - /*CMMB*/ - { "none", "none", "none", "cmmb_vega_12mhz.inp", "cmmb_venice_12mhz.inp", "cmmb_ming_app.inp", "none", "none", "none", "none" }, - /*RAW - not supported*/ - { "none", "none", "none", "none", "none", "none", "none", "none", "none", "none" }, - /*FM*/ - { "none", "none", "fm_radio.inp", "none", "none", "none", "none", "fm_radio_rio.inp", "none", "none" }, - /*FM_BDA*/ - { "none", "none", "fm_radio.inp", "none", "none", "none", "none", "fm_radio_rio.inp", "none", "none" }, - /*ATSC*/ - { "none", "none", "none", "none", "none", "none", "none", "none", "atsc_denver.inp", "none" } +static char *smscore_fw_lkup[][DEVICE_MODE_MAX] = { + [SMS_NOVA_A0] = { + [DEVICE_MODE_DVBT] = "dvb_nova_12mhz.inp", + [DEVICE_MODE_DVBH] = "dvb_nova_12mhz.inp", + [DEVICE_MODE_DAB_TDMB] = "tdmb_nova_12mhz.inp", + [DEVICE_MODE_DVBT_BDA] = "dvb_nova_12mhz.inp", + [DEVICE_MODE_ISDBT] = "isdbt_nova_12mhz.inp", + [DEVICE_MODE_ISDBT_BDA] = "isdbt_nova_12mhz.inp", + }, + [SMS_NOVA_B0] = { + [DEVICE_MODE_DVBT] = "dvb_nova_12mhz_b0.inp", + [DEVICE_MODE_DVBH] = "dvb_nova_12mhz_b0.inp", + [DEVICE_MODE_DAB_TDMB] = "tdmb_nova_12mhz_b0.inp", + [DEVICE_MODE_DVBT_BDA] = "dvb_nova_12mhz_b0.inp", + [DEVICE_MODE_ISDBT] = "isdbt_nova_12mhz_b0.inp", + [DEVICE_MODE_ISDBT_BDA] = "isdbt_nova_12mhz_b0.inp", + [DEVICE_MODE_FM_RADIO] = "fm_radio.inp", + [DEVICE_MODE_FM_RADIO_BDA] = "fm_radio.inp", + }, + [SMS_VEGA] = { + [DEVICE_MODE_CMMB] = "cmmb_vega_12mhz.inp", + }, + [SMS_VENICE] = { + [DEVICE_MODE_CMMB] = "cmmb_venice_12mhz.inp", + }, + [SMS_MING] = { + [DEVICE_MODE_CMMB] = "cmmb_ming_app.inp", + }, + [SMS_PELE] = { + [DEVICE_MODE_ISDBT] = "isdbt_pele.inp", + [DEVICE_MODE_ISDBT_BDA] = "isdbt_pele.inp", + }, + [SMS_RIO] = { + [DEVICE_MODE_DVBT] = "dvb_rio.inp", + [DEVICE_MODE_DVBH] = "dvbh_rio.inp", + [DEVICE_MODE_DVBT_BDA] = "dvb_rio.inp", + [DEVICE_MODE_ISDBT] = "isdbt_rio.inp", + [DEVICE_MODE_ISDBT_BDA] = "isdbt_rio.inp", + [DEVICE_MODE_FM_RADIO] = "fm_radio_rio.inp", + [DEVICE_MODE_FM_RADIO_BDA] = "fm_radio_rio.inp", + }, + [SMS_DENVER_1530] = { + [DEVICE_MODE_ATSC] = "atsc_denver.inp", + }, + [SMS_DENVER_2160] = { + [DEVICE_MODE_DAB_TDMB] = "tdmb_denver.inp", + }, }; /** @@ -1185,34 +1268,65 @@ static char *smscore_fw_lkup[][SMS_NUM_OF_DEVICE_TYPES] = { * @return 0 on success, <0 on error. */ static char *smscore_get_fw_filename(struct smscore_device_t *coredev, - int mode, int lookup) + int mode) { char **fw; int board_id = smscore_get_board_id(coredev); - enum sms_device_type_st type = smscore_registry_gettype(coredev->devpath); + enum sms_device_type_st type; - if ((board_id == SMS_BOARD_UNKNOWN) || (lookup == 1)) { - sms_debug("trying to get fw name from lookup table mode %d type %d", - mode, type); - return smscore_fw_lkup[mode][type]; - } + type = smscore_registry_gettype(coredev->devpath); + + /* Prevent looking outside the smscore_fw_lkup table */ + if (type <= SMS_UNKNOWN_TYPE || type >= SMS_NUM_OF_DEVICE_TYPES) + return NULL; + if (mode <= DEVICE_MODE_NONE || mode >= DEVICE_MODE_MAX) + return NULL; sms_debug("trying to get fw name from sms_boards board_id %d mode %d", board_id, mode); fw = sms_get_board(board_id)->fw; - if (fw == NULL) { + if (!fw || !fw[mode]) { sms_debug("cannot find fw name in sms_boards, getting from lookup table mode %d type %d", mode, type); - return smscore_fw_lkup[mode][type]; + return smscore_fw_lkup[type][mode]; } - if (fw[mode] == NULL) { - sms_debug("cannot find fw name in sms_boards, getting from lookup table mode %d type %d", - mode, type); - return smscore_fw_lkup[mode][type]; + return fw[mode]; +} + +/** + * send init device request and wait for response + * + * @param coredev pointer to a coredev object returned by + * smscore_register_device + * @param mode requested mode of operation + * + * @return 0 on success, <0 on error. + */ +int smscore_init_device(struct smscore_device_t *coredev, int mode) +{ + void *buffer; + struct SmsMsgData_ST *msg; + int rc = 0; + + buffer = kmalloc(sizeof(struct SmsMsgData_ST) + + SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA); + if (!buffer) { + sms_err("Could not allocate buffer for init device message."); + return -ENOMEM; } - return fw[mode]; + msg = (struct SmsMsgData_ST *)SMS_ALIGN_ADDRESS(buffer); + SMS_INIT_MSG(&msg->xMsgHeader, MSG_SMS_INIT_DEVICE_REQ, + sizeof(struct SmsMsgData_ST)); + msg->msgData[0] = mode; + + rc = smscore_sendrequest_and_wait(coredev, msg, + msg->xMsgHeader. msgLength, + &coredev->init_device_done); + + kfree(buffer); + return rc; } /** @@ -1231,7 +1345,7 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode) sms_debug("set device mode to %d", mode); if (coredev->device_flags & SMS_DEVICE_FAMILY2) { - if (mode < DEVICE_MODE_DVBT || mode >= DEVICE_MODE_RAW_TUNER) { + if (mode <= DEVICE_MODE_NONE || mode >= DEVICE_MODE_MAX) { sms_err("invalid mode specified %d", mode); return -EINVAL; } @@ -1253,32 +1367,20 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode) if (!(coredev->modes_supported & (1 << mode))) { rc = smscore_load_firmware_from_file(coredev, - mode, 0, NULL); - - /* - * try again with the default firmware - - * get the fw filename from look-up table - */ - if (rc < 0) { - sms_debug("error %d loading firmware, trying again with default firmware", - rc); - rc = smscore_load_firmware_from_file(coredev, - mode, 1, - NULL); - if (rc < 0) { - sms_debug("error %d loading firmware", - rc); - return rc; - } - } + mode, NULL); if (rc >= 0) sms_info("firmware download success"); } else { sms_info("mode %d is already supported by running firmware", mode); } + if (coredev->fw_version >= 0x800) { + rc = smscore_init_device(coredev, mode); + if (rc < 0) + sms_err("device init failed, rc %d.", rc); + } } else { - if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) { + if (mode <= DEVICE_MODE_NONE || mode >= DEVICE_MODE_MAX) { sms_err("invalid mode specified %d", mode); return -EINVAL; } @@ -1317,6 +1419,9 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode) if (rc < 0) sms_err("return error code %d.", rc); + else + sms_debug("Success setting device mode."); + return rc; } @@ -1420,6 +1525,20 @@ void smscore_onresponse(struct smscore_device_t *coredev, if (rc < 0) { switch (phdr->msgType) { + case MSG_SMS_ISDBT_TUNE_RES: + break; + case MSG_SMS_RF_TUNE_RES: + break; + case MSG_SMS_SIGNAL_DETECTED_IND: + break; + case MSG_SMS_NO_SIGNAL_IND: + break; + case MSG_SMS_SPI_INT_LINE_SET_RES: + break; + case MSG_SMS_INTERFACE_LOCK_IND: + break; + case MSG_SMS_INTERFACE_UNLOCK_IND: + break; case MSG_SMS_GET_VERSION_EX_RES: { struct SmsVersionRes_ST *ver = @@ -1885,7 +2004,6 @@ int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum, pMsg->msgData[5] = 0; } - smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg); rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen, &coredev->gpio_configuration_done); @@ -1935,7 +2053,6 @@ int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum, pMsg->msgData[1] = NewLevel; /* Send message to SMS */ - smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg); rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen, &coredev->gpio_set_level_done); @@ -1984,7 +2101,6 @@ int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum, pMsg->msgData[1] = 0; /* Send message to SMS */ - smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg); rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen, &coredev->gpio_get_level_done);