linux/drivers/media/usb/as102/as10x_cmd_cfg.c
<<
>>
Prefs
   1/*
   2 * Abilis Systems Single DVB-T Receiver
   3 * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License as published by
   7 * the Free Software Foundation; either version 2, or (at your option)
   8 * any later version.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 */
  15
  16#include <linux/kernel.h>
  17#include "as102_drv.h"
  18#include "as10x_cmd.h"
  19
  20/***************************/
  21/* FUNCTION DEFINITION     */
  22/***************************/
  23
  24/**
  25 * as10x_cmd_get_context - Send get context command to AS10x
  26 * @adap:      pointer to AS10x bus adapter
  27 * @tag:       context tag
  28 * @pvalue:    pointer where to store context value read
  29 *
  30 * Return 0 on success or negative value in case of error.
  31 */
  32int as10x_cmd_get_context(struct as10x_bus_adapter_t *adap, uint16_t tag,
  33                          uint32_t *pvalue)
  34{
  35        int  error;
  36        struct as10x_cmd_t *pcmd, *prsp;
  37
  38        pcmd = adap->cmd;
  39        prsp = adap->rsp;
  40
  41        /* prepare command */
  42        as10x_cmd_build(pcmd, (++adap->cmd_xid),
  43                        sizeof(pcmd->body.context.req));
  44
  45        /* fill command */
  46        pcmd->body.context.req.proc_id = cpu_to_le16(CONTROL_PROC_CONTEXT);
  47        pcmd->body.context.req.tag = cpu_to_le16(tag);
  48        pcmd->body.context.req.type = cpu_to_le16(GET_CONTEXT_DATA);
  49
  50        /* send command */
  51        if (adap->ops->xfer_cmd) {
  52                error  = adap->ops->xfer_cmd(adap,
  53                                             (uint8_t *) pcmd,
  54                                             sizeof(pcmd->body.context.req)
  55                                             + HEADER_SIZE,
  56                                             (uint8_t *) prsp,
  57                                             sizeof(prsp->body.context.rsp)
  58                                             + HEADER_SIZE);
  59        } else {
  60                error = AS10X_CMD_ERROR;
  61        }
  62
  63        if (error < 0)
  64                goto out;
  65
  66        /* parse response: context command do not follow the common response */
  67        /* structure -> specific handling response parse required            */
  68        error = as10x_context_rsp_parse(prsp, CONTROL_PROC_CONTEXT_RSP);
  69
  70        if (error == 0) {
  71                /* Response OK -> get response data */
  72                *pvalue = le32_to_cpu((__force __le32)prsp->body.context.rsp.reg_val.u.value32);
  73                /* value returned is always a 32-bit value */
  74        }
  75
  76out:
  77        return error;
  78}
  79
  80/**
  81 * as10x_cmd_set_context - send set context command to AS10x
  82 * @adap:      pointer to AS10x bus adapter
  83 * @tag:       context tag
  84 * @value:     value to set in context
  85 *
  86 * Return 0 on success or negative value in case of error.
  87 */
  88int as10x_cmd_set_context(struct as10x_bus_adapter_t *adap, uint16_t tag,
  89                          uint32_t value)
  90{
  91        int error;
  92        struct as10x_cmd_t *pcmd, *prsp;
  93
  94        pcmd = adap->cmd;
  95        prsp = adap->rsp;
  96
  97        /* prepare command */
  98        as10x_cmd_build(pcmd, (++adap->cmd_xid),
  99                        sizeof(pcmd->body.context.req));
 100
 101        /* fill command */
 102        pcmd->body.context.req.proc_id = cpu_to_le16(CONTROL_PROC_CONTEXT);
 103        /* pcmd->body.context.req.reg_val.mode initialization is not required */
 104        pcmd->body.context.req.reg_val.u.value32 = (__force u32)cpu_to_le32(value);
 105        pcmd->body.context.req.tag = cpu_to_le16(tag);
 106        pcmd->body.context.req.type = cpu_to_le16(SET_CONTEXT_DATA);
 107
 108        /* send command */
 109        if (adap->ops->xfer_cmd) {
 110                error  = adap->ops->xfer_cmd(adap,
 111                                             (uint8_t *) pcmd,
 112                                             sizeof(pcmd->body.context.req)
 113                                             + HEADER_SIZE,
 114                                             (uint8_t *) prsp,
 115                                             sizeof(prsp->body.context.rsp)
 116                                             + HEADER_SIZE);
 117        } else {
 118                error = AS10X_CMD_ERROR;
 119        }
 120
 121        if (error < 0)
 122                goto out;
 123
 124        /* parse response: context command do not follow the common response */
 125        /* structure -> specific handling response parse required            */
 126        error = as10x_context_rsp_parse(prsp, CONTROL_PROC_CONTEXT_RSP);
 127
 128out:
 129        return error;
 130}
 131
 132/**
 133 * as10x_cmd_eLNA_change_mode - send eLNA change mode command to AS10x
 134 * @adap:      pointer to AS10x bus adapter
 135 * @mode:      mode selected:
 136 *              - ON    : 0x0 => eLNA always ON
 137 *              - OFF   : 0x1 => eLNA always OFF
 138 *              - AUTO  : 0x2 => eLNA follow hysteresis parameters
 139 *                               to be ON or OFF
 140 *
 141 * Return 0 on success or negative value in case of error.
 142 */
 143int as10x_cmd_eLNA_change_mode(struct as10x_bus_adapter_t *adap, uint8_t mode)
 144{
 145        int error;
 146        struct as10x_cmd_t *pcmd, *prsp;
 147
 148        pcmd = adap->cmd;
 149        prsp = adap->rsp;
 150
 151        /* prepare command */
 152        as10x_cmd_build(pcmd, (++adap->cmd_xid),
 153                        sizeof(pcmd->body.cfg_change_mode.req));
 154
 155        /* fill command */
 156        pcmd->body.cfg_change_mode.req.proc_id =
 157                cpu_to_le16(CONTROL_PROC_ELNA_CHANGE_MODE);
 158        pcmd->body.cfg_change_mode.req.mode = mode;
 159
 160        /* send command */
 161        if (adap->ops->xfer_cmd) {
 162                error  = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd,
 163                                sizeof(pcmd->body.cfg_change_mode.req)
 164                                + HEADER_SIZE, (uint8_t *) prsp,
 165                                sizeof(prsp->body.cfg_change_mode.rsp)
 166                                + HEADER_SIZE);
 167        } else {
 168                error = AS10X_CMD_ERROR;
 169        }
 170
 171        if (error < 0)
 172                goto out;
 173
 174        /* parse response */
 175        error = as10x_rsp_parse(prsp, CONTROL_PROC_ELNA_CHANGE_MODE_RSP);
 176
 177out:
 178        return error;
 179}
 180
 181/**
 182 * as10x_context_rsp_parse - Parse context command response
 183 * @prsp:       pointer to AS10x command response buffer
 184 * @proc_id:    id of the command
 185 *
 186 * Since the contex command response does not follow the common
 187 * response, a specific parse function is required.
 188 * Return 0 on success or negative value in case of error.
 189 */
 190int as10x_context_rsp_parse(struct as10x_cmd_t *prsp, uint16_t proc_id)
 191{
 192        int err;
 193
 194        err = prsp->body.context.rsp.error;
 195
 196        if ((err == 0) &&
 197            (le16_to_cpu(prsp->body.context.rsp.proc_id) == proc_id)) {
 198                return 0;
 199        }
 200        return AS10X_CMD_ERROR;
 201}
 202