linux/drivers/staging/media/as102/as10x_cmd.c
<<
>>
Prefs
   1/*
   2 * Abilis Systems Single DVB-T Receiver
   3 * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
   4 * Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com>
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2, or (at your option)
   9 * any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program; if not, write to the Free Software
  18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19 */
  20
  21#include <linux/kernel.h>
  22#include "as102_drv.h"
  23#include "as10x_types.h"
  24#include "as10x_cmd.h"
  25
  26/**
  27 * as10x_cmd_turn_on - send turn on command to AS10x
  28 * @adap:   pointer to AS10x bus adapter
  29 *
  30 * Return 0 when no error, < 0 in case of error.
  31 */
  32int as10x_cmd_turn_on(struct as10x_bus_adapter_t *adap)
  33{
  34        int error = AS10X_CMD_ERROR;
  35        struct as10x_cmd_t *pcmd, *prsp;
  36
  37        ENTER();
  38
  39        pcmd = adap->cmd;
  40        prsp = adap->rsp;
  41
  42        /* prepare command */
  43        as10x_cmd_build(pcmd, (++adap->cmd_xid),
  44                        sizeof(pcmd->body.turn_on.req));
  45
  46        /* fill command */
  47        pcmd->body.turn_on.req.proc_id = cpu_to_le16(CONTROL_PROC_TURNON);
  48
  49        /* send command */
  50        if (adap->ops->xfer_cmd) {
  51                error = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd,
  52                                            sizeof(pcmd->body.turn_on.req) +
  53                                            HEADER_SIZE,
  54                                            (uint8_t *) prsp,
  55                                            sizeof(prsp->body.turn_on.rsp) +
  56                                            HEADER_SIZE);
  57        }
  58
  59        if (error < 0)
  60                goto out;
  61
  62        /* parse response */
  63        error = as10x_rsp_parse(prsp, CONTROL_PROC_TURNON_RSP);
  64
  65out:
  66        LEAVE();
  67        return error;
  68}
  69
  70/**
  71 * as10x_cmd_turn_off - send turn off command to AS10x
  72 * @adap:   pointer to AS10x bus adapter
  73 *
  74 * Return 0 on success or negative value in case of error.
  75 */
  76int as10x_cmd_turn_off(struct as10x_bus_adapter_t *adap)
  77{
  78        int error = AS10X_CMD_ERROR;
  79        struct as10x_cmd_t *pcmd, *prsp;
  80
  81        ENTER();
  82
  83        pcmd = adap->cmd;
  84        prsp = adap->rsp;
  85
  86        /* prepare command */
  87        as10x_cmd_build(pcmd, (++adap->cmd_xid),
  88                        sizeof(pcmd->body.turn_off.req));
  89
  90        /* fill command */
  91        pcmd->body.turn_off.req.proc_id = cpu_to_le16(CONTROL_PROC_TURNOFF);
  92
  93        /* send command */
  94        if (adap->ops->xfer_cmd) {
  95                error = adap->ops->xfer_cmd(
  96                        adap, (uint8_t *) pcmd,
  97                        sizeof(pcmd->body.turn_off.req) + HEADER_SIZE,
  98                        (uint8_t *) prsp,
  99                        sizeof(prsp->body.turn_off.rsp) + HEADER_SIZE);
 100        }
 101
 102        if (error < 0)
 103                goto out;
 104
 105        /* parse response */
 106        error = as10x_rsp_parse(prsp, CONTROL_PROC_TURNOFF_RSP);
 107
 108out:
 109        LEAVE();
 110        return error;
 111}
 112
 113/**
 114 * as10x_cmd_set_tune - send set tune command to AS10x
 115 * @adap:    pointer to AS10x bus adapter
 116 * @ptune:   tune parameters
 117 *
 118 * Return 0 on success or negative value in case of error.
 119 */
 120int as10x_cmd_set_tune(struct as10x_bus_adapter_t *adap,
 121                       struct as10x_tune_args *ptune)
 122{
 123        int error = AS10X_CMD_ERROR;
 124        struct as10x_cmd_t *preq, *prsp;
 125
 126        ENTER();
 127
 128        preq = adap->cmd;
 129        prsp = adap->rsp;
 130
 131        /* prepare command */
 132        as10x_cmd_build(preq, (++adap->cmd_xid),
 133                        sizeof(preq->body.set_tune.req));
 134
 135        /* fill command */
 136        preq->body.set_tune.req.proc_id = cpu_to_le16(CONTROL_PROC_SETTUNE);
 137        preq->body.set_tune.req.args.freq = cpu_to_le32(ptune->freq);
 138        preq->body.set_tune.req.args.bandwidth = ptune->bandwidth;
 139        preq->body.set_tune.req.args.hier_select = ptune->hier_select;
 140        preq->body.set_tune.req.args.modulation = ptune->modulation;
 141        preq->body.set_tune.req.args.hierarchy = ptune->hierarchy;
 142        preq->body.set_tune.req.args.interleaving_mode  =
 143                ptune->interleaving_mode;
 144        preq->body.set_tune.req.args.code_rate  = ptune->code_rate;
 145        preq->body.set_tune.req.args.guard_interval = ptune->guard_interval;
 146        preq->body.set_tune.req.args.transmission_mode  =
 147                ptune->transmission_mode;
 148
 149        /* send command */
 150        if (adap->ops->xfer_cmd) {
 151                error = adap->ops->xfer_cmd(adap,
 152                                            (uint8_t *) preq,
 153                                            sizeof(preq->body.set_tune.req)
 154                                            + HEADER_SIZE,
 155                                            (uint8_t *) prsp,
 156                                            sizeof(prsp->body.set_tune.rsp)
 157                                            + HEADER_SIZE);
 158        }
 159
 160        if (error < 0)
 161                goto out;
 162
 163        /* parse response */
 164        error = as10x_rsp_parse(prsp, CONTROL_PROC_SETTUNE_RSP);
 165
 166out:
 167        LEAVE();
 168        return error;
 169}
 170
 171/**
 172 * as10x_cmd_get_tune_status - send get tune status command to AS10x
 173 * @adap: pointer to AS10x bus adapter
 174 * @pstatus: pointer to updated status structure of the current tune
 175 *
 176 * Return 0 on success or negative value in case of error.
 177 */
 178int as10x_cmd_get_tune_status(struct as10x_bus_adapter_t *adap,
 179                              struct as10x_tune_status *pstatus)
 180{
 181        int error = AS10X_CMD_ERROR;
 182        struct as10x_cmd_t  *preq, *prsp;
 183
 184        ENTER();
 185
 186        preq = adap->cmd;
 187        prsp = adap->rsp;
 188
 189        /* prepare command */
 190        as10x_cmd_build(preq, (++adap->cmd_xid),
 191                        sizeof(preq->body.get_tune_status.req));
 192
 193        /* fill command */
 194        preq->body.get_tune_status.req.proc_id =
 195                cpu_to_le16(CONTROL_PROC_GETTUNESTAT);
 196
 197        /* send command */
 198        if (adap->ops->xfer_cmd) {
 199                error = adap->ops->xfer_cmd(
 200                        adap,
 201                        (uint8_t *) preq,
 202                        sizeof(preq->body.get_tune_status.req) + HEADER_SIZE,
 203                        (uint8_t *) prsp,
 204                        sizeof(prsp->body.get_tune_status.rsp) + HEADER_SIZE);
 205        }
 206
 207        if (error < 0)
 208                goto out;
 209
 210        /* parse response */
 211        error = as10x_rsp_parse(prsp, CONTROL_PROC_GETTUNESTAT_RSP);
 212        if (error < 0)
 213                goto out;
 214
 215        /* Response OK -> get response data */
 216        pstatus->tune_state = prsp->body.get_tune_status.rsp.sts.tune_state;
 217        pstatus->signal_strength  =
 218                le16_to_cpu(prsp->body.get_tune_status.rsp.sts.signal_strength);
 219        pstatus->PER = le16_to_cpu(prsp->body.get_tune_status.rsp.sts.PER);
 220        pstatus->BER = le16_to_cpu(prsp->body.get_tune_status.rsp.sts.BER);
 221
 222out:
 223        LEAVE();
 224        return error;
 225}
 226
 227/**
 228 * as10x_cmd_get_tps - send get TPS command to AS10x
 229 * @adap:      pointer to AS10x handle
 230 * @ptps:      pointer to TPS parameters structure
 231 *
 232 * Return 0 on success or negative value in case of error.
 233 */
 234int as10x_cmd_get_tps(struct as10x_bus_adapter_t *adap, struct as10x_tps *ptps)
 235{
 236        int error = AS10X_CMD_ERROR;
 237        struct as10x_cmd_t *pcmd, *prsp;
 238
 239        ENTER();
 240
 241        pcmd = adap->cmd;
 242        prsp = adap->rsp;
 243
 244        /* prepare command */
 245        as10x_cmd_build(pcmd, (++adap->cmd_xid),
 246                        sizeof(pcmd->body.get_tps.req));
 247
 248        /* fill command */
 249        pcmd->body.get_tune_status.req.proc_id =
 250                cpu_to_le16(CONTROL_PROC_GETTPS);
 251
 252        /* send command */
 253        if (adap->ops->xfer_cmd) {
 254                error = adap->ops->xfer_cmd(adap,
 255                                            (uint8_t *) pcmd,
 256                                            sizeof(pcmd->body.get_tps.req) +
 257                                            HEADER_SIZE,
 258                                            (uint8_t *) prsp,
 259                                            sizeof(prsp->body.get_tps.rsp) +
 260                                            HEADER_SIZE);
 261        }
 262
 263        if (error < 0)
 264                goto out;
 265
 266        /* parse response */
 267        error = as10x_rsp_parse(prsp, CONTROL_PROC_GETTPS_RSP);
 268        if (error < 0)
 269                goto out;
 270
 271        /* Response OK -> get response data */
 272        ptps->modulation = prsp->body.get_tps.rsp.tps.modulation;
 273        ptps->hierarchy = prsp->body.get_tps.rsp.tps.hierarchy;
 274        ptps->interleaving_mode = prsp->body.get_tps.rsp.tps.interleaving_mode;
 275        ptps->code_rate_HP = prsp->body.get_tps.rsp.tps.code_rate_HP;
 276        ptps->code_rate_LP = prsp->body.get_tps.rsp.tps.code_rate_LP;
 277        ptps->guard_interval = prsp->body.get_tps.rsp.tps.guard_interval;
 278        ptps->transmission_mode  = prsp->body.get_tps.rsp.tps.transmission_mode;
 279        ptps->DVBH_mask_HP = prsp->body.get_tps.rsp.tps.DVBH_mask_HP;
 280        ptps->DVBH_mask_LP = prsp->body.get_tps.rsp.tps.DVBH_mask_LP;
 281        ptps->cell_ID = le16_to_cpu(prsp->body.get_tps.rsp.tps.cell_ID);
 282
 283out:
 284        LEAVE();
 285        return error;
 286}
 287
 288/**
 289 * as10x_cmd_get_demod_stats - send get demod stats command to AS10x
 290 * @adap:          pointer to AS10x bus adapter
 291 * @pdemod_stats:  pointer to demod stats parameters structure
 292 *
 293 * Return 0 on success or negative value in case of error.
 294 */
 295int as10x_cmd_get_demod_stats(struct as10x_bus_adapter_t *adap,
 296                              struct as10x_demod_stats *pdemod_stats)
 297{
 298        int error = AS10X_CMD_ERROR;
 299        struct as10x_cmd_t *pcmd, *prsp;
 300
 301        ENTER();
 302
 303        pcmd = adap->cmd;
 304        prsp = adap->rsp;
 305
 306        /* prepare command */
 307        as10x_cmd_build(pcmd, (++adap->cmd_xid),
 308                        sizeof(pcmd->body.get_demod_stats.req));
 309
 310        /* fill command */
 311        pcmd->body.get_demod_stats.req.proc_id =
 312                cpu_to_le16(CONTROL_PROC_GET_DEMOD_STATS);
 313
 314        /* send command */
 315        if (adap->ops->xfer_cmd) {
 316                error = adap->ops->xfer_cmd(adap,
 317                                (uint8_t *) pcmd,
 318                                sizeof(pcmd->body.get_demod_stats.req)
 319                                + HEADER_SIZE,
 320                                (uint8_t *) prsp,
 321                                sizeof(prsp->body.get_demod_stats.rsp)
 322                                + HEADER_SIZE);
 323        }
 324
 325        if (error < 0)
 326                goto out;
 327
 328        /* parse response */
 329        error = as10x_rsp_parse(prsp, CONTROL_PROC_GET_DEMOD_STATS_RSP);
 330        if (error < 0)
 331                goto out;
 332
 333        /* Response OK -> get response data */
 334        pdemod_stats->frame_count =
 335                le32_to_cpu(prsp->body.get_demod_stats.rsp.stats.frame_count);
 336        pdemod_stats->bad_frame_count =
 337                le32_to_cpu(prsp->body.get_demod_stats.rsp.stats.bad_frame_count);
 338        pdemod_stats->bytes_fixed_by_rs =
 339                le32_to_cpu(prsp->body.get_demod_stats.rsp.stats.bytes_fixed_by_rs);
 340        pdemod_stats->mer =
 341                le16_to_cpu(prsp->body.get_demod_stats.rsp.stats.mer);
 342        pdemod_stats->has_started =
 343                prsp->body.get_demod_stats.rsp.stats.has_started;
 344
 345out:
 346        LEAVE();
 347        return error;
 348}
 349
 350/**
 351 * as10x_cmd_get_impulse_resp - send get impulse response command to AS10x
 352 * @adap:     pointer to AS10x bus adapter
 353 * @is_ready: pointer to value indicating when impulse
 354 *            response data is ready
 355 *
 356 * Return 0 on success or negative value in case of error.
 357 */
 358int as10x_cmd_get_impulse_resp(struct as10x_bus_adapter_t *adap,
 359                               uint8_t *is_ready)
 360{
 361        int error = AS10X_CMD_ERROR;
 362        struct as10x_cmd_t *pcmd, *prsp;
 363
 364        ENTER();
 365
 366        pcmd = adap->cmd;
 367        prsp = adap->rsp;
 368
 369        /* prepare command */
 370        as10x_cmd_build(pcmd, (++adap->cmd_xid),
 371                        sizeof(pcmd->body.get_impulse_rsp.req));
 372
 373        /* fill command */
 374        pcmd->body.get_impulse_rsp.req.proc_id =
 375                cpu_to_le16(CONTROL_PROC_GET_IMPULSE_RESP);
 376
 377        /* send command */
 378        if (adap->ops->xfer_cmd) {
 379                error = adap->ops->xfer_cmd(adap,
 380                                        (uint8_t *) pcmd,
 381                                        sizeof(pcmd->body.get_impulse_rsp.req)
 382                                        + HEADER_SIZE,
 383                                        (uint8_t *) prsp,
 384                                        sizeof(prsp->body.get_impulse_rsp.rsp)
 385                                        + HEADER_SIZE);
 386        }
 387
 388        if (error < 0)
 389                goto out;
 390
 391        /* parse response */
 392        error = as10x_rsp_parse(prsp, CONTROL_PROC_GET_IMPULSE_RESP_RSP);
 393        if (error < 0)
 394                goto out;
 395
 396        /* Response OK -> get response data */
 397        *is_ready = prsp->body.get_impulse_rsp.rsp.is_ready;
 398
 399out:
 400        LEAVE();
 401        return error;
 402}
 403
 404/**
 405 * as10x_cmd_build - build AS10x command header
 406 * @pcmd:     pointer to AS10x command buffer
 407 * @xid:      sequence id of the command
 408 * @cmd_len:  length of the command
 409 */
 410void as10x_cmd_build(struct as10x_cmd_t *pcmd,
 411                     uint16_t xid, uint16_t cmd_len)
 412{
 413        pcmd->header.req_id = cpu_to_le16(xid);
 414        pcmd->header.prog = cpu_to_le16(SERVICE_PROG_ID);
 415        pcmd->header.version = cpu_to_le16(SERVICE_PROG_VERSION);
 416        pcmd->header.data_len = cpu_to_le16(cmd_len);
 417}
 418
 419/**
 420 * as10x_rsp_parse - Parse command response
 421 * @prsp:       pointer to AS10x command buffer
 422 * @proc_id:    id of the command
 423 *
 424 * Return 0 on success or negative value in case of error.
 425 */
 426int as10x_rsp_parse(struct as10x_cmd_t *prsp, uint16_t proc_id)
 427{
 428        int error;
 429
 430        /* extract command error code */
 431        error = prsp->body.common.rsp.error;
 432
 433        if ((error == 0) &&
 434            (le16_to_cpu(prsp->body.common.rsp.proc_id) == proc_id)) {
 435                return 0;
 436        }
 437
 438        return AS10X_CMD_ERROR;
 439}
 440