/*
 * Production Data Area API for Conexant CX3110x chipset.
 *
 * Copyright (C) 2005 Nokia Corporation
 * Author: Samuel Ortiz <samuel.ortiz@nokia.com>
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 */
#ifndef _ISLSM_PDA_H
#define _ISLSM_PDA_H

#include <linux/types.h>
#include <linux/if_ether.h> /* for ETH_ALEN */

#define UINT16_GET(p) (*(uint16_t *)(p))


/*
 * this files defines the PDR codes used to build PDAs as defined in document
 * number 553155. The current implementation mirrors version 1.1 of the
 * document and lists only PDRs supported by the ARM platform.
 */

/* common and choice range (0x0000 - 0x0fff) */
#define PDR_END					0x0000
#define PDR_MANUFACTURING_PART_NUMBER		0x0001
#define PDR_PDA_VERSION				0x0002
#define PDR_NIC_SERIAL_NUMBER			0x0003

#define PDR_MAC_ADDRESS				0x0101
#define PDR_REGULATORY_DOMAIN_LIST		0x0103
#define PDR_TEMPERATURE_TYPE			0x0107

#define PDR_PRISM_PCI_IDENTIFIER		0x0402

/* ARM range (0x1000 - 0x1fff) */
#define PDR_COUNTRY_INFORMATION			0x1000
#define PDR_INTERFACE_LIST			0x1001
#define PDR_HARDWARE_PLATFORM_COMPONENT_ID	0x1002
#define PDR_OEM_NAME				0x1003
#define PDR_PRODUCT_NAME			0x1004
#define PDR_UTF8_OEM_NAME			0x1005
#define PDR_UTF8_PRODUCT_NAME			0x1006
#define PDR_COUNTRY_LIST			0x1007
#define PDR_DEFAULT_COUNTRY			0x1008

#define PDR_ANTENNA_GAIN			0x1100

#define PDR_PRISM_INDIGO_PA_CALIBRATION_DATA	0x1901
#define PDR_RSSI_LINEAR_APPROXIMATION		0x1902
#define PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS	0x1903
#define PDR_PRISM_PA_CAL_CURVE_DATA		0x1904
#define PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND	0x1905
#define PDR_PRISM_ZIF_TX_IQ_CALIBRATION     	0x1906
#define PDR_REGULATORY_POWER_LIMITS             0x1907
#define PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED  0x1908
#define PDR_RADIATED_TRANSMISSION_CORRECTION    0x1909
#define PDR_PRISM_TX_IQ_CALIBRATION             0x190a

/* reserved range (0x2000 - 0x7fff) */

/* customer range (0x8000 - 0xffff) */
#define PDR_BASEBAND_REGISTERS			0x8000
#define PDR_PER_CHANNEL_BASEBAND_REGISTERS	0x8001

/*
 * regulatory domain codes as defined in IEEE 802.11
 */
#define REGDOMAIN_FCC		0x10
#define REGDOMAIN_IC		0x20
#define REGDOMAIN_ETSI		0x30
#define REGDOMAIN_SPAIN		0x31
#define REGDOMAIN_FRANCE	0x32
#define REGDOMAIN_MKK		0x40    /* channel 14 only */
#define REGDOMAIN_MKK13         0x41    /* channel 1 to 13 */

#define MAX_ARM_PDR             32
#define PDR_SIZE_LENGTH         2
#define PDR_CODE_LENGTH         2


/* In most of the chips, the pda is in an eeprom. There's a small
   wrapper around the pda proper, which can be used to store init
   data for the ROM */
typedef struct eeprom_pda_wrap {
	/* magic1 is always the same thing */
#define EEPROM_START_MAGIC 0xaa554d47
	uint32_t                magic1;
	uint16_t                pad;
	uint16_t                data_length;
	uint32_t                arm_opcode;
	uint8_t                 data[];
} __attribute__ ((packed))
eeprom_pda_wrap_t;

typedef struct pda_entry_t_ {
	uint16_t size;
	uint16_t code;
	char     data[];
} __attribute__((packed)) pda_entry_t;

/*
 * PDR structures
 */
#define NUM_CHANNELS 13
#define POINTS_PER_CHANNEL 6

/* MAC address PDR 0x0101*/
struct wlan_pda_mac_addr_s {
	uint8_t	mac_addr[ETH_ALEN];
};

/* 1908, revision 08, seen on the Dell 1450 usb */
/* Two of them, for the two bands, I guess */
#define PERBAND_PDR1908_REV   0x08
struct wlan_pda_rssi_cal_band_s {
	/* three points, don't know what they really mean */
	uint16_t rssi_A;
	uint16_t rssi_B;
	uint16_t rssi_LNA;
} __attribute__ ((packed));

/* RSSI PDR 0x1908, unknown revision */
struct wlan_pda_rssi_cal_channel_s {
	uint16_t frequency;
	uint16_t rssi_A;
	uint16_t rssi_B;
	/* low noise amplifier */
	uint16_t rssi_LNA;
} __attribute__ ((packed));

struct wlan_pda_rssi_cal_s {
	uint8_t  pdr_revision;
	uint8_t  xcvr_bmp;
	struct wlan_pda_rssi_cal_channel_s rssi_data[];
} __attribute__ ((packed));

/* IQ calibration PDR 0x1906*/
struct wlan_pda_iq_autocal_s {
	uint16_t  frequency;
	uint16_t  iq_param_1;
	uint16_t  iq_param_2;
	uint16_t  iq_param_3;
	uint16_t  iq_param_4;
} __attribute__ ((packed));


/* Output limits PDR 0x1903 */
struct wlan_pda_output_limits_channel_s {
	uint16_t  frequency;
	uint8_t   rate_set_mask;
	uint8_t   rate_set_size;
	unsigned short   limit_barker;
	unsigned short   limit_bpsk;
	unsigned short   limit_qpsk;
	unsigned short   limit_16qam;
	unsigned short   limit_64qam;
} __attribute__ ((packed));

#define PHASER_PDR1903_REV   0x01
struct wlan_pda_output_limit_s {
	uint8_t  pdr_revision;
	uint8_t  xcvr_bmp;
	uint8_t  n_pa_levels;
	uint8_t  padding;
	struct wlan_pda_output_limits_channel_s  power[];
} __attribute__ ((packed));

#define ORIGINAL_PDR1903_REV   0x00
struct wlan_pda_output_limits_channel_rev0_s {
	uint16_t  frequency;
	uint8_t   val_bpsk;
	uint8_t   val_qpsk;
	uint8_t   val_16qam;
	uint8_t   val_64qam;
	/* don't really know what they are used for */
	uint8_t   rate_set_mask;
	uint8_t   rate_set_size;
} __attribute__ ((packed));

struct wlan_pda_output_limit_rev0_s {
	uint8_t  pdr_revision;
	uint8_t  n_channels;
	struct wlan_pda_output_limits_channel_rev0_s  power[];
} __attribute__ ((packed));


/* PA Curve data PDR 0x1904 */
struct wlan_pda_pa_curve_data_sample_s {
	uint16_t  rf_power;
	/* power amplifier detector */
	uint16_t  pa_detector;
	/* phase center variation */
	uint16_t  pcv;
} __attribute__ ((packed));

struct wlan_pda_pa_curve_data_channel_s {
	uint16_t frequency;
	uint16_t ladder;
	uint8_t  rate_set_mask;
	uint8_t  rate_set_size;
	struct wlan_pda_pa_curve_data_sample_s curve_samples [];
} __attribute__ ((packed));

#define PHASER_PA_CAL_METHOD   0x03
struct wlan_pda_pa_curve_data_s {
	uint8_t  cal_method_revision;
	/* transciever */
	uint8_t  xcvr_bmp;
	uint8_t  points_per_channel;
	uint8_t  padding;
	struct wlan_pda_pa_curve_data_channel_s curve_data[];
} __attribute__ ((packed));

#define ORIGINAL_PA_CAL_METHOD   0x00
#define GW_3887_PA_CAL_METHOD    0x01

struct wlan_pda_pa_curve_data_sample_rev1_s {
	uint8_t   rf_power;
	uint8_t   pa_detector;
	/* maybe pcv, maybe something else */
	uint8_t   data_barker;
	uint8_t   data_bpsk;
	uint8_t   data_qpsk;
	uint8_t   data_16qam;
	uint8_t   data_64qam;
} __attribute__ ((packed));

struct wlan_pda_pa_curve_data_sample_rev0_s {
	/* comparing with the N770 structures yields these meanings for
	 * the data samples -- but i'm unsure -- the rev1 sample has
	 * another interpretation */
	uint8_t                 rf_power;
	uint8_t                 pa_detector;
	uint8_t                 pcv;
} __attribute__ ((packed));

union wlan_pda_pa_curve_data_sample_old_s {
	struct wlan_pda_pa_curve_data_sample_rev0_s rev0;
	struct wlan_pda_pa_curve_data_sample_rev1_s rev1;
};

struct wlan_pda_pa_curve_data_channel_old_s {
	uint16_t frequency;
	union wlan_pda_pa_curve_data_sample_old_s curve_samples[];
} __attribute__ ((packed));

struct wlan_pda_pa_curve_data_old_s {
	uint8_t  cal_method_revision;
	uint8_t  n_channels;
	uint8_t  points_per_channel;
	uint8_t  padding;
	struct wlan_pda_pa_curve_data_channel_old_s curve_data[];
} __attribute__ ((packed));

/* entries in PDR 0x1007 and PDR 0x1008 for the Dell 1450.  I don't
   really know yet how to discriminate these from the entries of the
   type below -- probably on the first byte */
struct wlan_pda_country_s {
	uint8_t something;
	uint8_t code[2];
	uint8_t regulatory_domain;
} __attribute__ ((packed));

/* Default country PDR 0x1008 */
struct wlan_pda_default_country_s {
	uint8_t regulatory_domain;
	uint8_t country_code[3];
} __attribute__ ((packed));

/* PDR 0x1002 */
struct wlan_pda_hw_platform_split {
	uint8_t                 unk1;
#define HW_UNK1 0x03
	uint8_t                 isl;
#define HW_3887 0x87
#define HW_3880 0x86
#define HW_3886 0x80
#define HW_3890 0x90
#define HW_3892 0x92
	uint16_t                unk2;
#define HW_UNK2 0x5501
} __attribute__ ((packed));

union wlan_pda_hw_platform {
	uint32_t hw;
	struct wlan_pda_hw_platform_split split;
};

#endif /* _ISLSM_PDA_H */
