Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Abilis Systems Single DVB-T Receiver
0004  * Copyright (C) 2008 Pierrick Hascoet <pierrick.hascoet@abilis.com>
0005  * Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com>
0006  */
0007 
0008 #include <linux/kernel.h>
0009 #include "as102_drv.h"
0010 #include "as10x_cmd.h"
0011 
0012 /**
0013  * as10x_cmd_turn_on - send turn on command to AS10x
0014  * @adap:   pointer to AS10x bus adapter
0015  *
0016  * Return 0 when no error, < 0 in case of error.
0017  */
0018 int as10x_cmd_turn_on(struct as10x_bus_adapter_t *adap)
0019 {
0020     int error = AS10X_CMD_ERROR;
0021     struct as10x_cmd_t *pcmd, *prsp;
0022 
0023     pcmd = adap->cmd;
0024     prsp = adap->rsp;
0025 
0026     /* prepare command */
0027     as10x_cmd_build(pcmd, (++adap->cmd_xid),
0028             sizeof(pcmd->body.turn_on.req));
0029 
0030     /* fill command */
0031     pcmd->body.turn_on.req.proc_id = cpu_to_le16(CONTROL_PROC_TURNON);
0032 
0033     /* send command */
0034     if (adap->ops->xfer_cmd) {
0035         error = adap->ops->xfer_cmd(adap, (uint8_t *) pcmd,
0036                         sizeof(pcmd->body.turn_on.req) +
0037                         HEADER_SIZE,
0038                         (uint8_t *) prsp,
0039                         sizeof(prsp->body.turn_on.rsp) +
0040                         HEADER_SIZE);
0041     }
0042 
0043     if (error < 0)
0044         goto out;
0045 
0046     /* parse response */
0047     error = as10x_rsp_parse(prsp, CONTROL_PROC_TURNON_RSP);
0048 
0049 out:
0050     return error;
0051 }
0052 
0053 /**
0054  * as10x_cmd_turn_off - send turn off command to AS10x
0055  * @adap:   pointer to AS10x bus adapter
0056  *
0057  * Return 0 on success or negative value in case of error.
0058  */
0059 int as10x_cmd_turn_off(struct as10x_bus_adapter_t *adap)
0060 {
0061     int error = AS10X_CMD_ERROR;
0062     struct as10x_cmd_t *pcmd, *prsp;
0063 
0064     pcmd = adap->cmd;
0065     prsp = adap->rsp;
0066 
0067     /* prepare command */
0068     as10x_cmd_build(pcmd, (++adap->cmd_xid),
0069             sizeof(pcmd->body.turn_off.req));
0070 
0071     /* fill command */
0072     pcmd->body.turn_off.req.proc_id = cpu_to_le16(CONTROL_PROC_TURNOFF);
0073 
0074     /* send command */
0075     if (adap->ops->xfer_cmd) {
0076         error = adap->ops->xfer_cmd(
0077             adap, (uint8_t *) pcmd,
0078             sizeof(pcmd->body.turn_off.req) + HEADER_SIZE,
0079             (uint8_t *) prsp,
0080             sizeof(prsp->body.turn_off.rsp) + HEADER_SIZE);
0081     }
0082 
0083     if (error < 0)
0084         goto out;
0085 
0086     /* parse response */
0087     error = as10x_rsp_parse(prsp, CONTROL_PROC_TURNOFF_RSP);
0088 
0089 out:
0090     return error;
0091 }
0092 
0093 /**
0094  * as10x_cmd_set_tune - send set tune command to AS10x
0095  * @adap:    pointer to AS10x bus adapter
0096  * @ptune:   tune parameters
0097  *
0098  * Return 0 on success or negative value in case of error.
0099  */
0100 int as10x_cmd_set_tune(struct as10x_bus_adapter_t *adap,
0101                struct as10x_tune_args *ptune)
0102 {
0103     int error = AS10X_CMD_ERROR;
0104     struct as10x_cmd_t *preq, *prsp;
0105 
0106     preq = adap->cmd;
0107     prsp = adap->rsp;
0108 
0109     /* prepare command */
0110     as10x_cmd_build(preq, (++adap->cmd_xid),
0111             sizeof(preq->body.set_tune.req));
0112 
0113     /* fill command */
0114     preq->body.set_tune.req.proc_id = cpu_to_le16(CONTROL_PROC_SETTUNE);
0115     preq->body.set_tune.req.args.freq = (__force __u32)cpu_to_le32(ptune->freq);
0116     preq->body.set_tune.req.args.bandwidth = ptune->bandwidth;
0117     preq->body.set_tune.req.args.hier_select = ptune->hier_select;
0118     preq->body.set_tune.req.args.modulation = ptune->modulation;
0119     preq->body.set_tune.req.args.hierarchy = ptune->hierarchy;
0120     preq->body.set_tune.req.args.interleaving_mode  =
0121         ptune->interleaving_mode;
0122     preq->body.set_tune.req.args.code_rate  = ptune->code_rate;
0123     preq->body.set_tune.req.args.guard_interval = ptune->guard_interval;
0124     preq->body.set_tune.req.args.transmission_mode  =
0125         ptune->transmission_mode;
0126 
0127     /* send command */
0128     if (adap->ops->xfer_cmd) {
0129         error = adap->ops->xfer_cmd(adap,
0130                         (uint8_t *) preq,
0131                         sizeof(preq->body.set_tune.req)
0132                         + HEADER_SIZE,
0133                         (uint8_t *) prsp,
0134                         sizeof(prsp->body.set_tune.rsp)
0135                         + HEADER_SIZE);
0136     }
0137 
0138     if (error < 0)
0139         goto out;
0140 
0141     /* parse response */
0142     error = as10x_rsp_parse(prsp, CONTROL_PROC_SETTUNE_RSP);
0143 
0144 out:
0145     return error;
0146 }
0147 
0148 /**
0149  * as10x_cmd_get_tune_status - send get tune status command to AS10x
0150  * @adap: pointer to AS10x bus adapter
0151  * @pstatus: pointer to updated status structure of the current tune
0152  *
0153  * Return 0 on success or negative value in case of error.
0154  */
0155 int as10x_cmd_get_tune_status(struct as10x_bus_adapter_t *adap,
0156                   struct as10x_tune_status *pstatus)
0157 {
0158     int error = AS10X_CMD_ERROR;
0159     struct as10x_cmd_t  *preq, *prsp;
0160 
0161     preq = adap->cmd;
0162     prsp = adap->rsp;
0163 
0164     /* prepare command */
0165     as10x_cmd_build(preq, (++adap->cmd_xid),
0166             sizeof(preq->body.get_tune_status.req));
0167 
0168     /* fill command */
0169     preq->body.get_tune_status.req.proc_id =
0170         cpu_to_le16(CONTROL_PROC_GETTUNESTAT);
0171 
0172     /* send command */
0173     if (adap->ops->xfer_cmd) {
0174         error = adap->ops->xfer_cmd(
0175             adap,
0176             (uint8_t *) preq,
0177             sizeof(preq->body.get_tune_status.req) + HEADER_SIZE,
0178             (uint8_t *) prsp,
0179             sizeof(prsp->body.get_tune_status.rsp) + HEADER_SIZE);
0180     }
0181 
0182     if (error < 0)
0183         goto out;
0184 
0185     /* parse response */
0186     error = as10x_rsp_parse(prsp, CONTROL_PROC_GETTUNESTAT_RSP);
0187     if (error < 0)
0188         goto out;
0189 
0190     /* Response OK -> get response data */
0191     pstatus->tune_state = prsp->body.get_tune_status.rsp.sts.tune_state;
0192     pstatus->signal_strength  =
0193         le16_to_cpu((__force __le16)prsp->body.get_tune_status.rsp.sts.signal_strength);
0194     pstatus->PER = le16_to_cpu((__force __le16)prsp->body.get_tune_status.rsp.sts.PER);
0195     pstatus->BER = le16_to_cpu((__force __le16)prsp->body.get_tune_status.rsp.sts.BER);
0196 
0197 out:
0198     return error;
0199 }
0200 
0201 /**
0202  * as10x_cmd_get_tps - send get TPS command to AS10x
0203  * @adap:      pointer to AS10x handle
0204  * @ptps:      pointer to TPS parameters structure
0205  *
0206  * Return 0 on success or negative value in case of error.
0207  */
0208 int as10x_cmd_get_tps(struct as10x_bus_adapter_t *adap, struct as10x_tps *ptps)
0209 {
0210     int error = AS10X_CMD_ERROR;
0211     struct as10x_cmd_t *pcmd, *prsp;
0212 
0213     pcmd = adap->cmd;
0214     prsp = adap->rsp;
0215 
0216     /* prepare command */
0217     as10x_cmd_build(pcmd, (++adap->cmd_xid),
0218             sizeof(pcmd->body.get_tps.req));
0219 
0220     /* fill command */
0221     pcmd->body.get_tune_status.req.proc_id =
0222         cpu_to_le16(CONTROL_PROC_GETTPS);
0223 
0224     /* send command */
0225     if (adap->ops->xfer_cmd) {
0226         error = adap->ops->xfer_cmd(adap,
0227                         (uint8_t *) pcmd,
0228                         sizeof(pcmd->body.get_tps.req) +
0229                         HEADER_SIZE,
0230                         (uint8_t *) prsp,
0231                         sizeof(prsp->body.get_tps.rsp) +
0232                         HEADER_SIZE);
0233     }
0234 
0235     if (error < 0)
0236         goto out;
0237 
0238     /* parse response */
0239     error = as10x_rsp_parse(prsp, CONTROL_PROC_GETTPS_RSP);
0240     if (error < 0)
0241         goto out;
0242 
0243     /* Response OK -> get response data */
0244     ptps->modulation = prsp->body.get_tps.rsp.tps.modulation;
0245     ptps->hierarchy = prsp->body.get_tps.rsp.tps.hierarchy;
0246     ptps->interleaving_mode = prsp->body.get_tps.rsp.tps.interleaving_mode;
0247     ptps->code_rate_HP = prsp->body.get_tps.rsp.tps.code_rate_HP;
0248     ptps->code_rate_LP = prsp->body.get_tps.rsp.tps.code_rate_LP;
0249     ptps->guard_interval = prsp->body.get_tps.rsp.tps.guard_interval;
0250     ptps->transmission_mode  = prsp->body.get_tps.rsp.tps.transmission_mode;
0251     ptps->DVBH_mask_HP = prsp->body.get_tps.rsp.tps.DVBH_mask_HP;
0252     ptps->DVBH_mask_LP = prsp->body.get_tps.rsp.tps.DVBH_mask_LP;
0253     ptps->cell_ID = le16_to_cpu((__force __le16)prsp->body.get_tps.rsp.tps.cell_ID);
0254 
0255 out:
0256     return error;
0257 }
0258 
0259 /**
0260  * as10x_cmd_get_demod_stats - send get demod stats command to AS10x
0261  * @adap:          pointer to AS10x bus adapter
0262  * @pdemod_stats:  pointer to demod stats parameters structure
0263  *
0264  * Return 0 on success or negative value in case of error.
0265  */
0266 int as10x_cmd_get_demod_stats(struct as10x_bus_adapter_t *adap,
0267                   struct as10x_demod_stats *pdemod_stats)
0268 {
0269     int error = AS10X_CMD_ERROR;
0270     struct as10x_cmd_t *pcmd, *prsp;
0271 
0272     pcmd = adap->cmd;
0273     prsp = adap->rsp;
0274 
0275     /* prepare command */
0276     as10x_cmd_build(pcmd, (++adap->cmd_xid),
0277             sizeof(pcmd->body.get_demod_stats.req));
0278 
0279     /* fill command */
0280     pcmd->body.get_demod_stats.req.proc_id =
0281         cpu_to_le16(CONTROL_PROC_GET_DEMOD_STATS);
0282 
0283     /* send command */
0284     if (adap->ops->xfer_cmd) {
0285         error = adap->ops->xfer_cmd(adap,
0286                 (uint8_t *) pcmd,
0287                 sizeof(pcmd->body.get_demod_stats.req)
0288                 + HEADER_SIZE,
0289                 (uint8_t *) prsp,
0290                 sizeof(prsp->body.get_demod_stats.rsp)
0291                 + HEADER_SIZE);
0292     }
0293 
0294     if (error < 0)
0295         goto out;
0296 
0297     /* parse response */
0298     error = as10x_rsp_parse(prsp, CONTROL_PROC_GET_DEMOD_STATS_RSP);
0299     if (error < 0)
0300         goto out;
0301 
0302     /* Response OK -> get response data */
0303     pdemod_stats->frame_count =
0304         le32_to_cpu((__force __le32)prsp->body.get_demod_stats.rsp.stats.frame_count);
0305     pdemod_stats->bad_frame_count =
0306         le32_to_cpu((__force __le32)prsp->body.get_demod_stats.rsp.stats.bad_frame_count);
0307     pdemod_stats->bytes_fixed_by_rs =
0308         le32_to_cpu((__force __le32)prsp->body.get_demod_stats.rsp.stats.bytes_fixed_by_rs);
0309     pdemod_stats->mer =
0310         le16_to_cpu((__force __le16)prsp->body.get_demod_stats.rsp.stats.mer);
0311     pdemod_stats->has_started =
0312         prsp->body.get_demod_stats.rsp.stats.has_started;
0313 
0314 out:
0315     return error;
0316 }
0317 
0318 /**
0319  * as10x_cmd_get_impulse_resp - send get impulse response command to AS10x
0320  * @adap:     pointer to AS10x bus adapter
0321  * @is_ready: pointer to value indicating when impulse
0322  *        response data is ready
0323  *
0324  * Return 0 on success or negative value in case of error.
0325  */
0326 int as10x_cmd_get_impulse_resp(struct as10x_bus_adapter_t *adap,
0327                    uint8_t *is_ready)
0328 {
0329     int error = AS10X_CMD_ERROR;
0330     struct as10x_cmd_t *pcmd, *prsp;
0331 
0332     pcmd = adap->cmd;
0333     prsp = adap->rsp;
0334 
0335     /* prepare command */
0336     as10x_cmd_build(pcmd, (++adap->cmd_xid),
0337             sizeof(pcmd->body.get_impulse_rsp.req));
0338 
0339     /* fill command */
0340     pcmd->body.get_impulse_rsp.req.proc_id =
0341         cpu_to_le16(CONTROL_PROC_GET_IMPULSE_RESP);
0342 
0343     /* send command */
0344     if (adap->ops->xfer_cmd) {
0345         error = adap->ops->xfer_cmd(adap,
0346                     (uint8_t *) pcmd,
0347                     sizeof(pcmd->body.get_impulse_rsp.req)
0348                     + HEADER_SIZE,
0349                     (uint8_t *) prsp,
0350                     sizeof(prsp->body.get_impulse_rsp.rsp)
0351                     + HEADER_SIZE);
0352     }
0353 
0354     if (error < 0)
0355         goto out;
0356 
0357     /* parse response */
0358     error = as10x_rsp_parse(prsp, CONTROL_PROC_GET_IMPULSE_RESP_RSP);
0359     if (error < 0)
0360         goto out;
0361 
0362     /* Response OK -> get response data */
0363     *is_ready = prsp->body.get_impulse_rsp.rsp.is_ready;
0364 
0365 out:
0366     return error;
0367 }
0368 
0369 /**
0370  * as10x_cmd_build - build AS10x command header
0371  * @pcmd:     pointer to AS10x command buffer
0372  * @xid:      sequence id of the command
0373  * @cmd_len:  length of the command
0374  */
0375 void as10x_cmd_build(struct as10x_cmd_t *pcmd,
0376              uint16_t xid, uint16_t cmd_len)
0377 {
0378     pcmd->header.req_id = cpu_to_le16(xid);
0379     pcmd->header.prog = cpu_to_le16(SERVICE_PROG_ID);
0380     pcmd->header.version = cpu_to_le16(SERVICE_PROG_VERSION);
0381     pcmd->header.data_len = cpu_to_le16(cmd_len);
0382 }
0383 
0384 /**
0385  * as10x_rsp_parse - Parse command response
0386  * @prsp:       pointer to AS10x command buffer
0387  * @proc_id:    id of the command
0388  *
0389  * Return 0 on success or negative value in case of error.
0390  */
0391 int as10x_rsp_parse(struct as10x_cmd_t *prsp, uint16_t proc_id)
0392 {
0393     int error;
0394 
0395     /* extract command error code */
0396     error = prsp->body.common.rsp.error;
0397 
0398     if ((error == 0) &&
0399         (le16_to_cpu(prsp->body.common.rsp.proc_id) == proc_id)) {
0400         return 0;
0401     }
0402 
0403     return AS10X_CMD_ERROR;
0404 }